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.

on 2007-06-21 21:26

on 2007-06-21 21:31

I thingh that it is a bug 2007/6/21, rjprado@gmail.com <rjprado@gmail.com>:

on 2007-06-21 21:32

On Fri, Jun 22, 2007 at 04:25:04AM +0900, rjprado@gmail.com 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" http://en.wikipedia.org/wiki/Rounding_error > Thanks, > Roberto Prado. --Greg

on 2007-06-21 21:34

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: http://en.wikipedia.org/wiki/Floating_point James Edward Gray II

on 2007-06-21 21:34

On 6/21/07, rjprado@gmail.com <rjprado@gmail.com> 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 2007-06-21 21:43

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

on 2007-06-21 21:43

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

on 2007-06-21 21:48

thank you! 2007/6/21, MenTaLguY <mental@rydia.net>:

on 2007-06-21 21:50

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? > 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 2007-06-21 21:52

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? 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 2007-06-21 21:53

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

on 2007-06-21 21:55

On Jun 21, 3:21 pm, "rjpr...@gmail.com" <rjpr...@gmail.com> 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 2007-06-21 22:01

On Jun 21, 3:49 pm, "Adriano Ferreira" <a.r.ferre...@gmail.com> 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 2007-06-21 22:28

On Fri, 22 Jun 2007 05:00:03 +0900, "rjprado@gmail.com" <rjprado@gmail.com> 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

on 2007-06-21 22:57

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

on 2007-06-22 02:08

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

on 2007-06-22 02:46

Yukihiro Matsumoto 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 2007-06-22 02:49

On 6/21/07, Michael W. Ryder <_mwryder@worldnet.att.net> 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.

on 2007-06-22 04:03

On Jun 21, 2007, at 8:48 PM, Gregory Brown wrote: > On 6/21/07, Michael W. Ryder <_mwryder@worldnet.att.net> 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 ;-) -Rob Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

on 2007-06-22 04:21

Rob Biedenharn 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 2007-06-22 05:12

From: Michael W. Ryder [mailto:_mwryder@worldnet.att.net] : # 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. have you tried bigdecimal? irb(main):001:0> require 'bigdecimal' => true irb(main):002:0> a=BigDecimal("14.95") => #<BigDecimal:2867a5c,'0.1495E2',8(8)> irb(main):003:0> b=BigDecimal("0.6") => #<BigDecimal:28614b8,'0.6E0',4(8)> irb(main):004:0> c=BigDecimal("8.97") => #<BigDecimal:28e47b4,'0.897E1',8(8)> irb(main):005:0> d=BigDecimal("8.970000001") => #<BigDecimal:28dffe8,'0.8970000001E1',16(16)> irb(main):006:0> a*b == c => true irb(main):007:0> a*b == d => false irb(main):008:0> c == 8.97 => true bigdecimal notation is very handy for calculator-like applications since the raw input usually is of type string. kind regards -botp

on 2007-06-22 07:18

Hi, On 6/22/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote: > |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 Oracle uses base 100 floating numbers. http://download-west.oracle.com/docs/cd/B19306_01/...

on 2007-06-22 10:40

Peña wrote: > > irb(main):006:0> a*b == c > I'm not trying to denigrate the project but it looks like it is still in alpha stage while the IBM project seems to have been releasing production code for a while. It also is an IEEE standard, which may or may not mean anything. I hadn't known about the bigdecimal project before and may try comparing the results of it to the general decimal arithmetic package if I get time.

on 2007-06-22 15:49

On 6/22/07, Michael W. Ryder <_mwryder@worldnet.att.net> wrote: > I'm not trying to denigrate the project but it looks like it is still in > alpha stage while the IBM project seems to have been releasing > production code for a while. It also is an IEEE standard, which may or > may not mean anything. Um... BigDecimal part of the ruby standard library. What is 'alpha' about it?

on 2007-06-22 18:08

Michael W. Ryder wrote: > 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. Basically you are thinking of >> require "rational" => true >> Rational(1057,100).to_f => 10.57 Daniel

on 2007-06-22 20:51

Gregory Brown wrote: > On 6/22/07, Michael W. Ryder <_mwryder@worldnet.att.net> wrote: > >> I'm not trying to denigrate the project but it looks like it is still in >> alpha stage while the IBM project seems to have been releasing >> production code for a while. It also is an IEEE standard, which may or >> may not mean anything. > > Um... BigDecimal part of the ruby standard library. What is 'alpha' > about it? > My mistake. When I entered bigdecimal in the search screen at Ruby Forge it pointed me to the long decimal package. Searching for bigdecimal on ruby-lang.org came up with zero results. Where do I find more information on bigdecimal as it isn't listed in the on-line version of Pickaxe?

on 2007-06-22 21:13

On 6/21/07, Adriano Ferreira <a.r.ferreira@gmail.com> wrote: > 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? > > > > 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 Actually in any base there are fractions which cannot be represented with a FINITE number of digits. For instance in base 10: 1/3 = 0.33333333333....... -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/

on 2007-06-22 21:16

On 6/22/07, Michael W. Ryder <_mwryder@worldnet.att.net> wrote: > > > > My mistake. When I entered bigdecimal in the search screen at Ruby > Forge it pointed me to the long decimal package. Searching for > bigdecimal on ruby-lang.org came up with zero results. Where do I find > more information on bigdecimal as it isn't listed in the on-line version > of Pickaxe? http://www.ruby-doc.org/stdlib/libdoc/bigdecimal/r... There is also a page in the stdlib section of Pickaxe II

on 2007-06-22 21:17

Daniel DeLorme wrote: > => true > >> Rational(1057,100).to_f > => 10.57 > > Daniel > I have been using Business Basic for over 25 years and it is what I consider fixed point. For example, entering 'Print 14.95*.6' results in 8.97. The language uses a set precision which can be changed. For example if I tell it to print 120*.000003 with the default precision of 2 it displays 0. If I change the precision to 6 and tell it to print the same thing it displays .00036. The computer stores the result in the precision at the time of the operation so entering 'a=120*.000003' in precision 2 stores 0 in a. Changing the precision to 6 afterwards still shows that 0 is stored in a. This is not like Ruby using printf where different formats show different results.

on 2007-06-22 21:19

On 6/21/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote: > * fixed point number > * base 10 floating numbers > * comparison with epsilon > > Does anyone know how these languages get the correct result? matz, I don't know which Smalltalk he used, but I just tried it in Squeak and it evalutes to false, just like in Ruby. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/

on 2007-06-23 11:16

From: Michael W. Ryder [mailto:_mwryder@worldnet.att.net] # I have been using Business Basic for over 25 years and it is what I # consider fixed point. For example, entering 'Print 14.95*.6' # results in # 8.97. The language uses a set precision which can be changed. For # example if I tell it to print 120*.000003 with the default # precision of # 2 it displays 0. If I change the precision to 6 and tell it to print # the same thing it displays .00036. The computer stores the result in # the precision at the time of the operation so entering # 'a=120*.000003' # in precision 2 stores 0 in a. Changing the precision to 6 afterwards # still shows that 0 is stored in a. This is not like Ruby # using printf # where different formats show different results. w ruby's bigdecimal, you can be precise as much as you want (limit is on the computer's power and the programmer's imagination). it's being used not only in business but also in scientific labs (that is as far as what i've heard fr ruby jap gossip/chat rooms) this is one stupid example, irb(main):013:0> a=BigDecimal("0.0"+"0"*100+"1") => #<BigDecimal:28b4dd4,'0.1E-101',4(108)> irb(main):014:0> a+1 => #<BigDecimal:28b26ec,'0.1000000000 0000000000 0000000000 0000000000 000000000 0 0000000000 0000000000 0000000000 0000000000 0000000000 001E1',108(140)> irb(main):015:0> (a+1).to_s => "0.10000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000001E1" irb(main):016:0> (a+1).to_s.size => 107 irb(main):017:0> (a+1)*(a+1) => #<BigDecimal:28a995c,'0.1000000000 0000000000 0000000000 0000000000 000000000 0 0000000000 0000000000 0000000000 0000000000 0000000000 0020000000 0000000000 0 000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000 000000 00001E1',208(276)> irb(main):018:0> irb(main):019:0> ((a+1)*(a+1)).to_s => "0.10000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000002000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000001E1" irb(main):020:0> ((a+1)*(a+1)).to_s.size => 209 it's inspiring. really. kind regards -botp

on 2007-06-23 12:31

```
On 6/23/07, Peña, Botp <botp@delmonte-phil.com> wrote:
> # 'a=120*.000003'
Yes, basically what you are dealing with is how the object is
represented, and not how it really is:
irb(main):001:0> 1.0/9.0 + 8.0/9.0 == 1
=> true
irb(main):002:0> 1.0/9.0
=> 0.111111111111111
irb(main):003:0>
Pretty obvious what's going on there without looking at the source
code. If you 'really' want it the way it is, you use BigDecimal.
Again, LCD factor. What is the easiest way to appease your
programmer? You give them what you think they expect most of the
time. Most people don't need a BigDecimal.
Todd
```

on 2007-06-23 18:28

On 6/22/07, Rick DeNatale <rick.denatale@gmail.com> wrote: > On 6/21/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote: > matz, > > I don't know which Smalltalk he used, but I just tried it in Squeak > and it evalutes to false, just like in Ruby. Same for Gnu Smalltalk. R.

on 2007-06-23 20:08

Peña wrote: > > w ruby's bigdecimal, you can be precise as much as you want (limit is on the computer's power and the programmer's imagination). it's being used not only in business but also in scientific labs (that is as far as what i've heard fr ruby jap gossip/chat rooms) As a matter of fact, the BigDecimal library comes with some scientific routines as standard equipment, such as LU decomposition and Newton iteration. That isn't a great surprise to me, having once earned a living programming one of the most popular scientific machines ever, the IBM 1620, which was a variable-length decimal computer. I don't remember, but I think the SIMH project has an emulator: http://simh.trailing-edge.com/

on 2007-06-24 15:27

MenTaLguY: > 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

on 2007-06-24 18:52

Shot (Piotr Szotkowski) wrote: > MenTaLguY: > >> 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). Regards Stefan

on 2007-06-24 20:26

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). I'd prefer in_delta?, but I think this is a great idea. Maybe you should submit an RCR?

on 2007-06-24 23:32

On Mon, Jun 25, 2007 at 01:52:07AM +0900, Stefan Rusterholz wrote: > >> code, you may need to be more careful.) > > > > Any particular reason against using Float::EPSILON here? :) Comparing floating-point values different from 1.0? (also, greater errors) > > 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). That default value for delta makes no sense in general if you're using it as in the above example. Comparing the absolute difference against a fixed epsilon (especially Float::EPSILON) isn't normally as interesting as giving a bound for the relative error, so you'd at least need something like class Float def in_rdelta(other, rdelta = 1e-6) # or maybe no default at all? return true if self == other d = self.abs > other.abs ? (self - other) / self : (self - other) / other d.abs <= rdelta end end e = Float::EPSILON # => 2.22044604925031e-16 1.0.in_rdelta(1.000000000000000222, e) # => true 100.0.in_rdelta(100.000000000000021, e) # => true 100.0.in_rdelta(100.000000000000044, e) # => false 1.0.in_rdelta(1.000000000000000322, e) # => true 1.000000000000000322 == 1.000000000000000222 # => true "%20.18f" % 1.000000000000000322 # => "1.000000000000000222" # And you'd have to add an extra check if you want a different semantics # around 0.0: 0.0.in_rdelta(2.22e-16, 0.1) # => false 0.0.in_rdelta(2e-17, 0.99) # => false 0.0.in_rdelta(2e-20, 0.9999) # => false

on 2007-06-25 01:45

On 6/24/07, Mauricio Fernandez <mfp@acm.org> wrote: > class Float > def in_rdelta(other, rdelta = 1e-6) # or maybe no default at all? I'd say no default. If you're already doing a check for something being in delta of something else, you might as well specify what you're looking for.

on 2007-06-25 14:57

> On 6/21/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote: >> * fixed point number >> * base 10 floating numbers >> * comparison with epsilon >> >> Does anyone know how these languages get the correct result? > Rick Denatale wrote: > matz, > > I don't know which Smalltalk he used, but I just tried it in Squeak > and it evalutes to false, just like in Ruby. 7.4

on 2007-06-25 17:03

On 6/25/07, Lloyd Linklater <lloyd@2live4.com> wrote: > > > > I don't know which Smalltalk he used, but I just tried it in Squeak > > and it evalutes to false, just like in Ruby. > > 7.4 VisualWorks 7.4? (At least that seems to be a smalltalk with a version number of 7.4). (You are aware that theres more than one implementation of Smalltalk, and to give just a version number is very vague, right?)

on 2007-06-25 20:51

Logan Capaldo wrote: > VisualWorks 7.4? (At least that seems to be a smalltalk with a version > number of 7.4). > > (You are aware that theres more than one implementation of Smalltalk, > and to > give just a version number is very vague, right?) oops! Sorry. Yes, it is VisualWorks 7.4

on 2007-06-26 08:55

Hi, At Mon, 25 Jun 2007 01:52:07 +0900, Stefan Rusterholz wrote in [ruby-talk:256798]: > 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). What about Float#neary= ? :)

on 2007-06-26 09:12

```
Nobuyoshi Nakada wrote:
>
Float#=~ isn't being used for anything...
```