views:

136

answers:

3

in PHP

echo (int) ( (0.1+0.7) * 10 );

or in Ruby

p ((0.1+0.7) *10).to_i

the result is 7 instead of 8. it might be really hard to catch for such pitfalls. i think if in North America, it is less of a problem because we calculate prices up to how many cents, so $17.28 or $17.29 might be less of a problem. But in country like China or Hong Kong, the price can be just an integer. In this case, if our program is generous and just ask the customer for the integer portion of the price, then problems can arise if 8 becomes 7. So maybe we always need to be careful and use round() instead? Any other method avoid this pitfall?

+2  A: 

use rounding instead of just taking the integer part of the number (which .to_i or (int) is doing). In PHP, you could use:

echo round((0.1+0.7)*10);

I'm sure Ruby has a similar function, I just don't know what it's called.

Jonathan
+5  A: 

Don't use floating point math if you want exact answers. If you are summing up prices use fixed point arithmetic. If your smallest value is a cent then treat all prices as cents.

Steven
+1  A: 

Ruby's version of the round method works like this:

((0.1+0.7)*10).round  #=> 8

But as Steven points out, floating point arithmetic can be alarmingly inaccurate. For better accuracy in Ruby you can use BigDecimal:

a = BigDecimal.new(0.1.to_s)
b = BigDecimal.new(0.7.to_s)
((a+b)*10)  #=> returns a BigDecimal with a value of 8.0

BigDecimal instances are initialized from strings, not floats. Thus the .to_s calls above.

Jesse Hallett