This happens in all languages that use floating point to represent decimal numbers (you will get precisely the same result in C or Javascript or Perl, for instance). Floating-point arithmetic is only approximate, so the result does not _exactly_ equal 8.97, even though it is very close.
Because of this, when using floating-point arithmetic, testing for exact equality is impractical. The best you can do is test whether the result is within some interval (epsilon) of the expected result:
( ( 14.95 * 0.6 ) - 8.97 ).abs < 1e-6
(Here, we've chosen 1e-6 as our epsilon, which is arbitrary but probably "small enough" in this case. For mathematically intensive code, you may need to be more careful.)
Although floating-point is the default for Ruby, you do have the option of using a different representation of numbers for which arithmetic is exact, although it will not be as fast. One such option is the Rational class in Ruby's standard library, which represents numbers as fractions rather than floating-point numbers.
-mental
···
On Fri, 22 Jun 2007 04:25:04 +0900, "rjprado@gmail.com" <rjprado@gmail.com> wrote:
Dear friends, today I have stumbled into a really weird problem. Try
typing this on irb:
On Fri, 22 Jun 2007 04:25:04 +0900, "rjprado@gmail.com" <rjprado@gmail.com> > wrote:
> Dear friends, today I have stumbled into a really weird problem. Try
> typing this on irb:
>
> 14.95 * 0.6 == 8.97
>
> Ruby says it's false!
This happens in all languages that use floating point to represent decimal
numbers (you will get precisely the same result in C or Javascript or Perl,
for instance). Floating-point arithmetic is only approximate, so the result
does not _exactly_ equal 8.97, even though it is very close.
Because of this, when using floating-point arithmetic, testing for exact
equality is impractical. The best you can do is test whether the result is
within some interval (epsilon) of the expected result:
( ( 14.95 * 0.6 ) - 8.97 ).abs < 1e-6
(Here, we've chosen 1e-6 as our epsilon, which is arbitrary but probably
"small enough" in this case. For mathematically intensive code, you may
need to be more careful.)
Although floating-point is the default for Ruby, you do have the option of
using a different representation of numbers for which arithmetic is exact,
although it will not be as fast. One such option is the Rational class in
Ruby's standard library, which represents numbers as fractions rather than
floating-point numbers.
And if you are using test/unit then use the assertion method
assert_in_delta()
- nasir
···
On 6/21/07, MenTaLguY <mental@rydia.net> wrote:
On Fri, 22 Jun 2007 04:25:04 +0900, "rjprado@gmail.com" <rjprado@gmail.com> > wrote:
> Dear friends, today I have stumbled into a really weird problem. Try
> typing this on irb:
>
> 14.95 * 0.6 == 8.97
>
> Ruby says it's false!
This happens in all languages that use floating point to represent decimal
numbers (you will get precisely the same result in C or Javascript or Perl,
for instance). Floating-point arithmetic is only approximate, so the result
does not _exactly_ equal 8.97, even though it is very close.
Because of this, when using floating-point arithmetic, testing for exact
equality is impractical. The best you can do is test whether the result is
within some interval (epsilon) of the expected result:
( ( 14.95 * 0.6 ) - 8.97 ).abs < 1e-6
(Here, we've chosen 1e-6 as our epsilon, which is arbitrary but probably
"small enough" in this case. For mathematically intensive code, you may
need to be more careful.)
Although floating-point is the default for Ruby, you do have the option of
using a different representation of numbers for which arithmetic is exact,
although it will not be as fast. One such option is the Rational class in
Ruby's standard library, which represents numbers as fractions rather than
floating-point numbers.
The best you can do is test whether the result is
within some interval (epsilon) of the expected result:
( ( 14.95 * 0.6 ) - 8.97 ).abs < 1e-6
(Here, we've chosen 1e-6 as our epsilon, which is arbitrary but
probably "small enough" in this case. For mathematically intensive
code, you may need to be more careful.)
Any particular reason against using Float::EPSILON here?
Maybe Float#== could simply be extended to consider the above? That
would most probably open another can of worms, though, and extending
Float#<=> would open yet another, I guess.
-- Shot
···
--
I'm not much of a kernel hacker, but a quick (and not very efficient,
granted) fix could be to make the offset an extern variable, yes?
That would force the compiler to fall back on the basic "your gun,
your foot, your choice" memory model. -- jtv, LKML
The best you can do is test whether the result is
within some interval (epsilon) of the expected result:
( ( 14.95 * 0.6 ) - 8.97 ).abs < 1e-6
(Here, we've chosen 1e-6 as our epsilon, which is arbitrary but
probably "small enough" in this case. For mathematically intensive
code, you may need to be more careful.)
Any particular reason against using Float::EPSILON here?
Maybe Float#== could simply be extended to consider the above? That
would most probably open another can of worms, though, and extending
Float#<=> would open yet another, I guess.
-- Shot
I think Float#== as it is is fine. Arguably it could use delta
comparison with Float::EPSILON and leave the exact comparison to eql?
But I'd like it if Float#in_delta(other, delta=Float::EPSILON) was in
core (personally I add it in my libs as Numeric#in_delta).
Some numbers (like 0.1) cannot be represented exactly in binary with a
finite number of bits (because 0.1[base 10] =
0.0001100110011001100110011...[base 2]) and when they are represented
(as it happens with floating point representations), they lose
precision. So you must not test floating point for equality but always
rely on some tolerance and use an expression like MenTaLguY showed:
( 14.95 * 0.6 - 8.97 ).abs < tol
where tol depends on your application.
···
On 6/21/07, juan pedro meriño <juapdiaz@gmail.com> wrote:
You are rigth James, but you can better reponse why is a floating point
error?
Not all numbers can be represented by an arbitrarily small number of digits, and floating-point numbers only have so many digits available (for Ruby, 53 binary digits, which is about 16 decimal digits). In this case, the computation required more than 53 bits, so the result was approximate.
-mental
···
On Fri, 22 Jun 2007 04:40:29 +0900, "juan pedro meriño" <juapdiaz@gmail.com> wrote:
You are rigth James, but you can better reponse why is a floating point
error?
>I tried this in Delphi, smalltalk and oracle SQL and got the correct >result.
Interesting. There are a few ways to get the "correct" result.
* fixed point number
* base 10 floating numbers
* comparison with epsilon
Does anyone know how these languages get the correct result?
matz.
A simple way to get the correct figure is to do what is used often with currency to prevent these types of errors. If I enter 'puts 1495.0*6.0/1000.0' I get 8.97. The only thing necessary is to keep track of the number of decimal points.
···
In message "Re: Ruby doesn't know how to multiply" > on Fri, 22 Jun 2007 05:57:48 +0900, Lloyd Linklater <lloyd@2live4.com> writes:
I'd prefer in_delta?, but I think this is a great idea. Maybe you
should submit an RCR?
···
On 6/24/07, Stefan Rusterholz <apeiros@gmx.net> wrote:
I think Float#== as it is is fine. Arguably it could use delta
comparison with Float::EPSILON and leave the exact comparison to eql?
But I'd like it if Float#in_delta(other, delta=Float::EPSILON) was in
core (personally I add it in my libs as Numeric#in_delta).