Ruby doesn't know how to multiply

Hello,

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!

I don’t know if this is a bug. Please let me know. By the way i´m on
ruby 1.8.5. I’ll give it a try on 1.8.6 and let you know.

Thanks,
Roberto Prado.

I thingh that it is a bug

2007/6/21, [email protected] [email protected]:

On Fri, Jun 22, 2007 at 04:25:04AM +0900, [email protected] wrote:

ruby 1.8.5. I’ll give it a try on 1.8.6 and let you know.
% irb

“%2.40f” % (14.95 * 0.6)
=> “8.9699999999999988631316227838397026062012”
“%2.40f” % 8.97
=> “8.9700000000000006394884621840901672840118”

Thanks,
Roberto Prado.
–Greg

On 6/21/07, [email protected] [email protected] wrote:

ruby 1.8.5. I’ll give it a try on 1.8.6 and let you know.
It’s not a bug. It’s the way floating point arithmetic works, and is
true for most programming languages.

http://docs.sun.com/source/806-3568/ncg_goldberg.html

On Jun 21, 2007, at 2:30 PM, juan pedro meriño wrote:

I thingh that it is a bug

It’s not. It’s a typical floating point error:

James Edward G. II

On Fri, 22 Jun 2007 04:25:04 +0900, “[email protected]
[email protected] 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.

-mental

You are rigth James, but you can better reponse why is a floating point
error?

On 6/21/07, juan pedro meriño [email protected] wrote:

You are rigth James, but you can better reponse why is a floating point
error?

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.

thank you!

2007/6/21, MenTaLguY [email protected]:

On Fri, 22 Jun 2007 04:40:29 +0900, “juan pedro meriño”
[email protected] 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

And if you are using test/unit then use the assertion method
assert_in_delta()

  • nasir

On Jun 21, 3:49 pm, “Adriano F.” [email protected] wrote:

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.

I’m starting to remember something about that on my computer
architecture course. But it’s something so technical and I’m so used
to high level programming, that I couldn’t remember…

On Jun 21, 3:21 pm, “[email protected][email protected] wrote:

ruby 1.8.5. I’ll give it a try on 1.8.6 and let you know.

Thanks,
Roberto Prado.

Yes, you are all right. It’s a common problem. I have confirmed this
by doing the same thing on java. Thank you all for your fast replies.

Greetings,
Roberto Prado.

On Fri, 22 Jun 2007 05:00:03 +0900, “[email protected]
[email protected] wrote:

I’m starting to remember something about that on my computer
architecture course. But it’s something so technical and I’m so used
to high level programming, that I couldn’t remember…

I guess it goes to show that one never really escapes this stuff,
even in “high level” programming.

-mental

Yes, you are all right. It’s a common problem. I have confirmed this
by doing the same thing on java. Thank you all for your fast replies.

I tried this in Delphi, smalltalk and oracle SQL and got the correct
result.

C# and visual C++ seem to it to be false.

This is most perplexing.

Yukihiro M. wrote:

  • 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.

On 6/21/07, Michael W. Ryder [email protected] wrote:

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.

Much better is to store the numbers as integers and convert to
decimal, guaranteeing zero loss.

Hi,

In message “Re: Ruby doesn’t know how to multiply”
on Fri, 22 Jun 2007 05:57:48 +0900, Lloyd L.
[email protected] writes:

|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.

Rob B. wrote:

Which are just different ways of saying “fixed point numbers” that matz
had at the top of his list. Believe me when I tell you that dealing
with fixed point can be challenging. I worked on part of an air traffic
control system about 20 years ago that used 16-bit values where the LSB
for a distance value represented 1/256nm (nautical mile). There was no
floating-point co-processor in the M68000-based systems and the C code
was compiled with a special, non-standard compiler that would do things
like (16-bits * 16-bits)/16-bits was assumed to produce a 16-bit result
unless you had a typecast to indicate otherwise.

I think we have a difference of understanding of what fixed point means.
I look at fixed point numbers meaning something like 1057 means 10.57
in the real world. I was thinking more of something that shifted the
floating point number to remove the fractions and later replaced the
decimal point in the correct position, which I do not consider to be
fixed point math.
My simple calculator is more precise for some math operations than my
expensive PC. Maybe we need to implement something like General Decimal
Arithmetic which is available for C++ and Java at
http://www2.hursley.ibm.com/decimal/ in Ruby. It may be as simple as
writing wrappers for the operations, I haven’t had to time to look
closer at the package.

On Jun 21, 2007, at 8:48 PM, Gregory B. wrote:

On 6/21/07, Michael W. Ryder [email protected] wrote:

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.

Much better is to store the numbers as integers and convert to
decimal, guaranteeing zero loss.

Which are just different ways of saying “fixed point numbers” that
matz had at the top of his list. Believe me when I tell you that
dealing with fixed point can be challenging. I worked on part of an
air traffic control system about 20 years ago that used 16-bit values
where the LSB for a distance value represented 1/256nm (nautical
mile). There was no floating-point co-processor in the M68000-based
systems and the C code was compiled with a special, non-standard
compiler that would do things like (16-bits * 16-bits)/16-bits was
assumed to produce a 16-bit result unless you had a typecast to
indicate otherwise.

The other way to get truth from 14.95*0.6 == 8.97 is to use less
precise representations than you get with a typical Float. Of
course, that’s going to be a problem as the numbers get bigger :wink:

-Rob

Rob B. http://agileconsultingllc.com
[email protected]