How Good Is This?
02 JAN
>> a = 79.99 * 100
=> 7999.0
>> a.floor
=> 7998
>> b = 7999.0
=> 7999.0
>> b.floor
=> 7999
I’ll tell you. It’s not good. I hate floating point calculations. Happy new year!
18 Comments (Closed)
Wow! That’s a problem. Also, a == b returns false. This seems like a Ruby bug to me.
Wyatt at 02.01.08 / 13PM
When I try this in the Firebug console, I actually get a value of 7998.999999 for the first calculation, which explains the weird a.floor result… Doesn’t make things any better though.
Ron at 02.01.08 / 13PM
No, this is not a bug. It’s just the nature of floating point math. If you need to compare floats, then you need to use a delta (Google for “ruby floating point compare” or something like that).
Jeremy at 02.01.08 / 13PM
No, you’re right. It’s not a bug. It’s what most languages do with floating points. It’s more of a gotcha.
The thing that I thought was odd was that Ruby shows the result of the first calculation as you’d like rather than doing what JavaScript does (7998.999999) but the underlying number is actually more like 7998.99999 than the 7999.0 that Ruby tells you it is. I just found that misleading.
Dan at 02.01.08 / 14PM
I can’t try this out right here, but can you tell me what happens when you do this? >> c = 79.99 * 100.0 => ? >> c.floor => ?
Jaap at 02.01.08 / 14PM
Yup… good gotchas indeed!
In the same vein:
require 'math'
=>true
(log(1000)/log(10)+1).to_i
=>3
1000.to_s.size
=>4
:(
BlackPignouf at 02.01.08 / 15PM
Jaap: you get 7998 again but if you do 799.9 * 10.0 and floor that you get 7999. This kind of thing is what always happens though. Its just Ruby’s inspect looking correct that confused me.
Dan at 02.01.08 / 16PM
If you need closer to exact floating point calculations without the rounding error, try the ruby BigDecimal library. It appears to use an internal string representation of floating point numbers, and uses them for calculation, so there is no ‘machine delta’ problem. It is a bit slower than straight floating point math, but if the result being accurate is more important…
korishev at 02.01.08 / 17PM
Hola, soy Herzeleyd y estoy buscando diseñadores para crear un logo de mi web, todo lo que pido y ofrezco lo podreis encontrar aquí http://www.herzeleyd.com/2008/01/03/busco-disenadores-para-crear-un-logo-en-mi-web/
Espero que no os incomode el mensaje.
Cualquier diseñador, amigo, blogger o lo que sea que conozcais, que pudiera estar dispuesto a presentar un logo, sería de gran ayuda. Cuanta más gente lo sepa y pueda ayudar, mucho mejor.
Muchas gracias a tod@s.
Herzeleyd at 03.01.08 / 20PM
Hi Dan, I get the same thing in python:
import math a = 79.99 * 100 math.floor(a) 7998.0 b = 7999.0 math.floor(b) 7999.0
Gary Stidston-Broadbent at 05.01.08 / 14PM
Go with BigDecimal.
ynw at 07.01.08 / 23PM
Hi there, same happens in matlab, which is meant for technical computing. a = 79.99*100 b = 7999 floor(a) = 7998 floor(b) = 7999 When I subtract both number (b-a) I get a difference of 9.094947017729282e-013 which is 2^12 times the machine precision. I know its a gotcha in floating point arithmetic but it would be cool if someone could give a thorough explanation of what exactly “goes wrong” here.
Jeroen at 09.01.08 / 10AM
Jeroen, Wikipedia is your friend And they can explain floating point accuracy problems much better than I.
korishev at 13.01.08 / 06AM
And, confirming what Wikipedia states, Perl (actually the POSIX math library so this affects C as well) has the same rounding trouble. Cranking up the precision here to expose it:
$ perl -e ‘use POSIX qw(floor); $a=79.99*100; printf “a=.22f\nfloor(a)=.22f\n”, $a, floor($a);$b=7999.0; printf “b=.22f\nfloor(b)=.22f\n”, $b, floor($b);’
Outputs: a=7998.9999999999990905052982 floor(a)=7998.0000000000000000000000 b=7999.0000000000000000000000 floor(b)=7999.0000000000000000000000
Steve at 17.01.08 / 21PM
Great :). Happy new year too you. Greetings
Noclegi at 19.01.08 / 16PM
Thanks korishev, interesting stuff …
Jeroen at 21.01.08 / 12PM
For what it’s worth, some microprocessors have had BCD (binary coded decimal) modes. The 6502 was one.
timothytoe at 01.02.08 / 21PM
Floating points are approximations, always have been. You need to do some magic to compare them, but it’s possible. There is a short book floating around somewhere called “what every computer science major should know about floating points” or something like that. It’s helpful if you can find it.
Xac Stegner at 24.03.08 / 23PM