From: Steven D'Aprano Date: 2008-12-24T17:26:19+09:00 Subject: Re: about Float On Fri, 19 Dec 2008 14:51:29 -0500, Christophe Mckeon wrote: > and just in case you need further convincing, this is the scariest > example i've ever seen. taken from Stefano Taschini's > http://intervals.rubyforge.org/ The example you give is pretty scary, but there's much scarier. You don't need a big complicated function to hit weird floating point anomalies. x + y - y should always equal x, right? irb(main):012:0> 1.0 + 3.0 - 3.0 => 1.0 Seems to work. Except when it doesn't... irb(main):017:0> x = 1.0/3 => 0.333333333333333 irb(main):018:0> x + 0.1 - 0.1 == x => false > Take into consideration the rather innocent looking function > > def f(x,y) > (333.75-x**2)* y**6 + x**2 * (11* x**2 * y**2-121 * y**4 -2) + > 5.5 * y**8 + x/(2*y) > end You've obviously lived a depraved life if you think that looks innocent :-) > We can calculate it for some specific x and y, > > f(77617.0,33096.0) # => 1.17260394005318 > > There is only one problem: this result is WRONG. The correct result can > be obtained by calculating separately the numerator and denominator of f > using integer arithmetic. Out of curiosity, I tried this equation in Python, and got the same result. Hardly surprising, as Python and Ruby will probably be using the same floating point library. I also tried in on my HP-48GX calculator, and got the same result too. If arithmetic truths could be voted on, that would be three votes for the wrong answer :) Does anyone have access to Mathematica? What does it give? > def f_num(x,y) > ((33375- 100 * x**2)* y**6 + > 100 * x**2 * (11* x**2 * y**2-121 * y**4 -2) + 550 * y**8) * > 2*y + 100 *x > end > > def f_den(x,y) > 200*y > end > > f_num(77617, 33096).to_f / f_den(77617, 33096).to_f > # => -0.827396059946821 Just to add more confusion to the story, here's another mathematically equivalent expression (unless I've made a silly mistake): irb(main):026:0> def f2(x, y) irb(main):027:1> a = x**2 irb(main):028:1> b = y**2 irb(main):029:1> f = x/(2*y) irb(main):030:1> 11*a*b*(a - 11*b)+(333.75 - a)*b**3 + 5.5*b**4 - 2*a+f irb(main):031:1> end => nil irb(main):032:0> f2(77617, 33096) => -12048797377.0 The moral of the story? Floats are evil. They are just similar enough to the real numbers you learn about in school to fool you into thinking that they behave just like reals, but they don't. -- Steven