Ruby can't subtract ?

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

  1. 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
    #1
    1. Advertising

  2. 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
    #2
    1. Advertising

  3. 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
    #3
  4. 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
    #4
  5. 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
    #5
  6. 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
    #6
  7. 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
    #7
  8. 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
    #8
  9. Aldric Giacomoni

    Gary Wright Guest

    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
    representation problem that most often leads to a thread such
    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
    #9
  10. 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
    #10
  11. Aldric Giacomoni

    Gary Wright Guest

    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
    #11
  12. 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,
    Rajinder Yadav

    http://DevMentor.org

    Do Good! - Share Freely, Enrich and Empower people to Transform their lives.
    Rajinder Yadav, Oct 29, 2009
    #12
  13. Rajinder Yadav 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?

    >
    > --
    > Kind Regards,
    > Rajinder Yadav
    >
    > 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
    #13
  14. Marnen Laibow-Koser wrote:
    > Rajinder Yadav 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,
    Rajinder Yadav

    http://DevMentor.org

    Do Good! - Share Freely, Enrich and Empower people to Transform their lives.
    Rajinder Yadav, Oct 29, 2009
    #14
  15. 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
    #15
  16. 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
    #16
  17. Aldric Giacomoni, Oct 29, 2009
    #17
  18. Rajinder Yadav, Oct 30, 2009
    #18
  19. 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
    #19
  20. 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
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Manoj Nair
    Replies:
    4
    Views:
    21,294
    Manoj Nair
    Sep 4, 2003
  2. Lutek

    How to subtract dates ?

    Lutek, Jan 4, 2005, in forum: Java
    Replies:
    6
    Views:
    52,967
    pac0rro
    Apr 3, 2009
  3. Multibyte add & subtract

    , Apr 28, 2006, in forum: C Programming
    Replies:
    2
    Views:
    350
    Rod Pemberton
    Apr 29, 2006
  4. Replies:
    8
    Views:
    437
    osmium
    Oct 14, 2006
  5. Ed Taylor
    Replies:
    3
    Views:
    86
    alex23
    Nov 19, 2013
Loading...

Share This Page