# Ruby can't subtract ?

Discussion in 'Ruby' started by Aldric Giacomoni, Oct 28, 2009.

1. ### Aldric GiacomoniGuest

I found this blog entry:
http://raveendran.wordpress.com/2009/06/29/ruby-big-decimal/
Which shows the following..

irb(main):011:0> require 'bigdecimal'
=> true
irb(main):012:0> x = BigDecimal("123.6") - BigDecimal("123")
=> #<BigDecimal:28c5b84,'0.6E0',4(16)>
irb(main):013:0> puts x.to_f
0.6
=> nil
irb(main):014:0> puts f=123.6 - 123
0.599999999999994
=> nil
irb(main):015:0> 123.6 - 123
=> 0.599999999999994
irb(main):016:0> 123.6 - 123.0
=> 0.599999999999994
irb(main):017:0>

That's a little strange.. Isn't it?
--
Posted via http://www.ruby-forum.com/.

Aldric Giacomoni, Oct 28, 2009

2. ### Matthew K. WilliamsGuest

On Thu, 29 Oct 2009, Aldric Giacomoni wrote:

> I found this blog entry:
> http://raveendran.wordpress.com/2009/06/29/ruby-big-decimal/
> Which shows the following..
>
> irb(main):011:0> require 'bigdecimal'
> => true
> irb(main):012:0> x = BigDecimal("123.6") - BigDecimal("123")
> => #<BigDecimal:28c5b84,'0.6E0',4(16)>
> irb(main):013:0> puts x.to_f
> 0.6
> => nil
> irb(main):014:0> puts f=123.6 - 123
> 0.599999999999994
> => nil
> irb(main):015:0> 123.6 - 123
> => 0.599999999999994
> irb(main):016:0> 123.6 - 123.0
> => 0.599999999999994
> irb(main):017:0>
>
> That's a little strange.. Isn't it?

No, it's not. Welcome to the wonderfully confusing world of floating
point math...

Matthew K. Williams, Oct 28, 2009

3. ### Aldric GiacomoniGuest

Matthew K. Williams wrote:
>> irb(main):016:0> 123.6 - 123.0
>> => 0.599999999999994
>>
>> That's a little strange.. Isn't it?

>
> No, it's not. Welcome to the wonderfully confusing world of floating
> point math...

Oh, thanks. Can I have some pop-corn and an introductory pamphlet before
I bash my head against the wall?
--
Posted via http://www.ruby-forum.com/.

Aldric Giacomoni, Oct 28, 2009
4. ### Matthew K. WilliamsGuest

On Thu, 29 Oct 2009, Aldric Giacomoni wrote:

> Matthew K. Williams wrote:
>>> irb(main):016:0> 123.6 - 123.0
>>> => 0.599999999999994
>>>
>>> That's a little strange.. Isn't it?

>>
>> No, it's not. Welcome to the wonderfully confusing world of floating
>> point math...

>
> Oh, thanks. Can I have some pop-corn and an introductory pamphlet before
> I bash my head against the wall?

Pamphlet -> http://en.wikipedia.org/wiki/IEEE_754-2008

Popcorn, well, it's kinda hard to transmit over the wire. ;-)

As a rule of thumb, if you really care about the decimals, either use
BigDecimal or integers (and keep track of where the decimal should be --
this is common for \$\$\$\$). Unfortunately, this is not limited to ruby,
either -- C, Java, and a host of other languages all are subject.

Matt

Matthew K. Williams, Oct 28, 2009
5. ### Aldric GiacomoniGuest

Matthew K. Williams wrote:
> On Thu, 29 Oct 2009, Aldric Giacomoni wrote:
>
>> I bash my head against the wall?

> Pamphlet -> http://en.wikipedia.org/wiki/IEEE_754-2008
>
> Popcorn, well, it's kinda hard to transmit over the wire. ;-)
>
> As a rule of thumb, if you really care about the decimals, either use
> BigDecimal or integers (and keep track of where the decimal should be --
> this is common for \$\$\$\$). Unfortunately, this is not limited to ruby,
> either -- C, Java, and a host of other languages all are subject.
>
> Matt

Thanks. Both my head and the wall are safe for now. As one may have
surmised, I don't deal with floating point values much, but this is
frustrating. I do see that there are a couple of people who wrote gems
on Rubyforge to handle this issue
--
Posted via http://www.ruby-forum.com/.

Aldric Giacomoni, Oct 28, 2009
6. ### Marnen Laibow-KoserGuest

Aldric Giacomoni wrote:
> Matthew K. Williams wrote:
>>> irb(main):016:0> 123.6 - 123.0
>>> => 0.599999999999994
>>>
>>> That's a little strange.. Isn't it?

>>
>> No, it's not. Welcome to the wonderfully confusing world of floating
>> point math...

>
> Oh, thanks. Can I have some pop-corn and an introductory pamphlet before
> I bash my head against the wall?

Most languages these days use IEEE 754-style floats, which leads to the
imprecision you saw.

http://c2.com/cgi/wiki?IeeeSevenFiftyFour

Don't use floats for serious arithmetic.

Best,
--
Marnen Laibow-Koser
http://www.marnen.org

--
Posted via http://www.ruby-forum.com/.

Marnen Laibow-Koser, Oct 28, 2009
7. ### Robert KlemmeGuest

On 28.10.2009 19:21, Matthew K. Williams wrote:
> On Thu, 29 Oct 2009, Aldric Giacomoni wrote:
>
>> Matthew K. Williams wrote:
>>>> irb(main):016:0> 123.6 - 123.0
>>>> => 0.599999999999994
>>>>
>>>> That's a little strange.. Isn't it?
>>> No, it's not. Welcome to the wonderfully confusing world of floating
>>> point math...

>> Oh, thanks. Can I have some pop-corn and an introductory pamphlet before
>> I bash my head against the wall?

>
> Pamphlet -> http://en.wikipedia.org/wiki/IEEE_754-2008
>
> Popcorn, well, it's kinda hard to transmit over the wire. ;-)

Easy to do with a modern email client - just needs support for POP3 and
a working firewall (for the heat).

> As a rule of thumb, if you really care about the decimals, either use
> BigDecimal or integers (and keep track of where the decimal should be --
> this is common for \$\$\$\$). Unfortunately, this is not limited to ruby,
> either -- C, Java, and a host of other languages all are subject.

Absolutely: this is a common issue in *all* programming languages which
are not systems for symbolic math (like Mathematica) because they do not
work with real numbers but just rational numbers.

Cheers

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Robert Klemme, Oct 28, 2009
8. ### Marnen Laibow-KoserGuest

Robert Klemme wrote:
> On 28.10.2009 19:21, Matthew K. Williams wrote:
>>> I bash my head against the wall?

>>
>> Pamphlet -> http://en.wikipedia.org/wiki/IEEE_754-2008
>>
>> Popcorn, well, it's kinda hard to transmit over the wire. ;-)

>
> Easy to do with a modern email client - just needs support for POP3 and
> a working firewall (for the heat).

LOL!

>
>> As a rule of thumb, if you really care about the decimals, either use
>> BigDecimal or integers (and keep track of where the decimal should be --
>> this is common for \$\$\$\$). Unfortunately, this is not limited to ruby,
>> either -- C, Java, and a host of other languages all are subject.

>
> Absolutely: this is a common issue in *all* programming languages which
> are not systems for symbolic math (like Mathematica) because they do not
> work with real numbers but just rational numbers.

That is not the issue here -- after all, BigDecimal does precise
arithmetic, but only with rational numbers. The issue is rather that
IEEE 754 does an inadequate job of representing arbitrary rational
numbers, and the small errors are accumulated and magnified in
calculations.

>
> Cheers
>
> robert

Best,
--
Marnen Laibow-Koser
http://www.marnen.org

--
Posted via http://www.ruby-forum.com/.

Marnen Laibow-Koser, Oct 28, 2009
9. ### Gary WrightGuest

On Oct 28, 2009, at 3:30 PM, Marnen Laibow-Koser wrote:
> That is not the issue here -- after all, BigDecimal does precise
> arithmetic, but only with rational numbers. The issue is rather that
> IEEE 754 does an inadequate job of representing arbitrary rational
> numbers, and the small errors are accumulated and magnified in
> calculations.

I'd like to emphasize the fact that it is a very specific
as this. That problem is a misunderstanding about the nature
of converting between a base 10 literal and a base 2 internal
value.

Many people don't realize that floating point literals written
in base 10 (such as 123.6) may not have an exact finite
representation when converted to base 2 and similarly a finite
base 2 floating point value may not have a finite representation
in base 10.

In the original post the floating point subtraction in the
expression (123.6 - 123.0) is handled just fine. The problem
is that 123.6 can't be represented exactly as a base 2 floating
point value so the subtraction that actually gets done is

123.599999999999994315658113919198513031005859375 - 123.0

and the result

0.599999999999994315658113919198513031005859375

is rounded via Ruby's Float#to_s method to

0.599999999999994

Gary Wright

Gary Wright, Oct 28, 2009
10. ### Marnen Laibow-KoserGuest

Gary Wright wrote:
[...].
>
>
> Many people don't realize that floating point literals written
> in base 10 (such as 123.6) may not have an exact finite
> representation when converted to base 2

Right. 0.6 in binary has a repeating decimal -- 0.1001 repeating or
something like that.

> and similarly a finite
> base 2 floating point value may not have a finite representation
> in base 10.

[...]

I think not. Every number of the form 1/(2^n) has a terminating decimal
in base 10. Am I wrong?

The problems, of course, arise with numbers like 1/3, which doesn't
terminate in either base. This is what the Rational class is good for.

>

Best,
--
Marnen Laibow-Koser
http://www.marnen.org

--
Posted via http://www.ruby-forum.com/.

Marnen Laibow-Koser, Oct 28, 2009
11. ### Gary WrightGuest

On Oct 28, 2009, at 5:14 PM, Marnen Laibow-Koser wrote:
>> and similarly a finite
>> base 2 floating point value may not have a finite representation
>> in base 10.

> [...]
>
> I think not. Every number of the form 1/(2^n) has a terminating
> decimal
> in base 10. Am I wrong?
>
> The problems, of course, arise with numbers like 1/3, which doesn't
> terminate in either base. This is what the Rational class is good
> for.

I spoke to quickly and had in mind what you just
suggested, that there are numbers that don't terminate
in either base.

But my main point was that people become aware of
these issues via the conversion problem rather than
via the nuances of IEEE floating point arithmetic.

Gary Wright

Gary Wright, Oct 28, 2009

Aldric Giacomoni wrote:
> I found this blog entry:
> http://raveendran.wordpress.com/2009/06/29/ruby-big-decimal/
> Which shows the following..
>
> irb(main):011:0> require 'bigdecimal'
> => true
> irb(main):012:0> x = BigDecimal("123.6") - BigDecimal("123")
> => #<BigDecimal:28c5b84,'0.6E0',4(16)>
> irb(main):013:0> puts x.to_f
> 0.6
> => nil
> irb(main):014:0> puts f=123.6 - 123
> 0.599999999999994
> => nil
> irb(main):015:0> 123.6 - 123
> => 0.599999999999994
> irb(main):016:0> 123.6 - 123.0
> => 0.599999999999994
> irb(main):017:0>
>
> That's a little strange.. Isn't it?

I've been following this thread and am wondering if there are other numerical
classes for Ruby other than BigDecimal?

--
Kind Regards,

http://DevMentor.org

Do Good! - Share Freely, Enrich and Empower people to Transform their lives.

13. ### Marnen Laibow-KoserGuest

[...]
> I've been following this thread and am wondering if there are other
> numerical
> classes for Ruby other than BigDecimal?

Well, I mentioned Rational. There's also Bignum, but that's
transparent, so it doesn't need to be called explicitly as BigDecimal
does. Check the standard library docs.

Were you looking for something specific?

>
> --
> Kind Regards,
>
> http://DevMentor.org
>
> Do Good! - Share Freely, Enrich and Empower people to Transform their
> lives.

Best,
--
Marnen Laibow-Koser
http://www.marnen.org

--
Posted via http://www.ruby-forum.com/.

Marnen Laibow-Koser, Oct 29, 2009

Marnen Laibow-Koser wrote:
> [...]
>> I've been following this thread and am wondering if there are other
>> numerical
>> classes for Ruby other than BigDecimal?

>
> Well, I mentioned Rational. There's also Bignum, but that's
> transparent, so it doesn't need to be called explicitly as BigDecimal
> does. Check the standard library docs.
>
> Were you looking for something specific?

Hi Marnen,

thanks for the reply. I am aware of Bignum and understand how Ruby does the
translation transparently from Fixnum. I was just seeking more knowledge outside
my current understanding of Ruby.

I had imagined there might be a class Currency =), again just wanting to know
what's available to me through Ruby.

> Best,
> --
> Marnen Laibow-Koser
> http://www.marnen.org
>

--
Kind Regards,

http://DevMentor.org

Do Good! - Share Freely, Enrich and Empower people to Transform their lives.

15. ### Christopher DicelyGuest

On Wed, Oct 28, 2009 at 12:30 PM, Marnen Laibow-Koser <> w=
rote:
> Robert Klemme wrote:
>> On 28.10.2009 19:21, Matthew K. Williams wrote:
>>>> I bash my head against the wall?
>>>
>>> Pamphlet -> http://en.wikipedia.org/wiki/IEEE_754-2008
>>>
>>> Popcorn, well, it's kinda hard to transmit over the wire. ;-)

>>
>> Easy to do with a modern email client - just needs support for POP3 and
>> a working firewall (for the heat).

>
> LOL!
>
>>
>>> As a rule of thumb, if you really care about the decimals, either use
>>> BigDecimal or integers (and keep track of where the decimal should be -=

-
>>> this is common for \$\$\$\$). =C2=A0Unfortunately, this is not limited to r=

uby,
>>> either -- C, Java, and a host of other languages all are subject.

>>
>> Absolutely: this is a common issue in *all* programming languages which
>> are not systems for symbolic math (like Mathematica) because they do not
>> work with real numbers but just rational numbers.

>
> That is not the issue here -- after all, BigDecimal does precise
> arithmetic, but only with rational numbers.

BigDecimal actually works with decimal numbers, which are a subset of
rational numbers; Rational does precise math with rational numbers.

>=C2=A0The issue is rather that IEEE 754 does an inadequate job of represen=

ting
> arbitrary rational numbers, and the small errors are accumulated and
> magnified in calculations.

The bigger issue is that Ruby -- like most general purpose programming
languages, though there are exceptions like Scheme -- makes IEEE 754
floating point the easiest non-integer data type to use, rather than
using exact numbers by default and using inexact numbers only when
explicitly called for (or when an operation that produces inexact
results is used.)

Christopher Dicely, Oct 29, 2009
16. ### Marnen Laibow-KoserGuest

Christopher Dicely wrote:
> On Wed, Oct 28, 2009 at 12:30 PM, Marnen Laibow-Koser
> <> wrote:
>>
>>> work with real numbers but just rational numbers.

>>
>> That is not the issue here -- after all, BigDecimal does precise
>> arithmetic, but only with rational numbers.

>
> BigDecimal actually works with decimal numbers, which are a subset of
> rational numbers; Rational does precise math with rational numbers.
>

You're quite right, and I realized that about 10 seconds after I posted.

>>Â The issue is rather that IEEE 754 does an inadequate job of representing
>> arbitrary rational numbers, and the small errors are accumulated and
>> magnified in calculations.

>
> The bigger issue is that Ruby -- like most general purpose programming
> languages, though there are exceptions like Scheme -- makes IEEE 754
> floating point the easiest non-integer data type to use, rather than
> using exact numbers by default and using inexact numbers only when
> explicitly called for (or when an operation that produces inexact
> results is used.)

Yup. At least Ruby took a step in the right direction by making Bignum
transparent; it would be lovely if some future version did likewise with
BigDecimal.

Best,
--
Marnen Laibow-Koser
http://www.marnen.org

--
Posted via http://www.ruby-forum.com/.

Marnen Laibow-Koser, Oct 29, 2009
17. ### Aldric GiacomoniGuest

Aldric Giacomoni, Oct 29, 2009

19. ### George NeunerGuest

On Wed, 28 Oct 2009 14:30:21 -0500, Marnen Laibow-Koser
<> wrote:

>Robert Klemme wrote:
>> On 28.10.2009 19:21, Matthew K. Williams wrote:
>>>> I bash my head against the wall?
>>>
>>> Pamphlet -> http://en.wikipedia.org/wiki/IEEE_754-2008
>>>
>>> Popcorn, well, it's kinda hard to transmit over the wire. ;-)

>>
>> Easy to do with a modern email client - just needs support for POP3 and
>> a working firewall (for the heat).

>
>LOL!
>
>>
>>> As a rule of thumb, if you really care about the decimals, either use
>>> BigDecimal or integers (and keep track of where the decimal should be --
>>> this is common for \$\$\$\$). Unfortunately, this is not limited to ruby,
>>> either -- C, Java, and a host of other languages all are subject.

>>
>> Absolutely: this is a common issue in *all* programming languages which
>> are not systems for symbolic math (like Mathematica) because they do not
>> work with real numbers but just rational numbers.

>
>That is not the issue here -- after all, BigDecimal does precise
>arithmetic, but only with rational numbers. The issue is rather that
>IEEE 754 does an inadequate job of representing arbitrary rational
>numbers, and the small errors are accumulated and magnified in
>calculations.

The problem is that the 754 representation has finite precision. I
suppose you can call that "inadequate", but I don't see a good way
around it ... 0.6 is still infinite in binary. BigDecimal will get
you the right answer (unless you run out of memory), but when the
significant figures pile up it tends to get you there very slowly. All
the various arbitrary precision formats suffer badly performance wise.

It's also worth noting that most floating point hardware is not
anywhere close to 754 compliant even though most FPUs do use the
standard number formats (at least for single and double precision).

George

George Neuner, Oct 31, 2009
20. ### Robert KlemmeGuest

On 10/31/2009 07:35 AM, George Neuner wrote:

> It's also worth noting that most floating point hardware is not
> anywhere close to 754 compliant even though most FPUs do use the
> standard number formats (at least for single and double precision).

Interesting! I wasn't aware of that. Why is that? Do they just leave
out operations or are HW vendors actually cutting corners and digressing
from the prescribed algorithms / results?

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Robert Klemme, Oct 31, 2009