Behavior of 0 and 0.0...

Discussion in 'Ruby' started by Raphael Clancy, Jan 9, 2009.

  1. I was playing around with the basic math functions, and I had some
    questions about the way Ruby handles operations with 0 and 0.0.

    first we have:

    $ ruby -v
    ruby 1.8.6 (2007-09-24 patchlevel 111) [i486-linux]
    $ irb
    irb(main):001:0> 0/0
    ZeroDivisionError: divided by 0
    from (irb):1:in `/'
    from (irb):1

    This is OK, it lets us know that we made a mistake somewhere, but when
    we try 0.0/0.0 we get:

    irb(main):002:0> 0.0/0.0
    => NaN

    Mathematically, this is preferable to division error, but, maybe not
    from a programming standpoint? The question here is why should these two
    events generate different results?

    Now, if we try something like 4.0/0.0 we get, what I would consider,
    really weird behavior:

    irb(main):003:0> 4.0/0.0
    => Infinity

    It is true that as x approaches 0 the limit of 1/x goes to infinity, but
    this is not the same as 1/0 = infinity. In this case why would infinity
    be preferable to the simpler result, NaN? At first I thought this might
    be a precision error, that is the parser is saying that 0.0 is not
    really 0, just very close. But, if that was the case then 0.0/0.0 would
    be 1 instead of NaN.

    Thanks!
    --
    Posted via http://www.ruby-forum.com/.
    Raphael Clancy, Jan 9, 2009
    #1
    1. Advertising

  2. Raphael Clancy

    Gary Wright Guest

    [Note: parts of this message were removed to make it a legal post.]


    On Jan 9, 2009, at 3:51 PM, Raphael Clancy wrote:

    > I was playing around with the basic math functions, and I had some
    > questions about the way Ruby handles operations with 0 and 0.0.


    I'm guessing that you are seeing IEEE floating point behavior with
    the floating point operations and that there isn't a perfect analog
    to that behavior with integer operations. IEEE floating
    point defines binary representations of negative and positive zero,
    negative and positive infinity, and two types of NaN (not a number).
    These 'numbers' aren't available when working with integers at the
    machine level nor at the Ruby Fixnum or Bignum level.

    Gary Wright
    Gary Wright, Jan 9, 2009
    #2
    1. Advertising

  3. Gary Wright wrote:
    >
    > On Jan 9, 2009, at 3:51 PM, Raphael Clancy wrote:
    >
    >> I was playing around with the basic math functions, and I had some
    >> questions about the way Ruby handles operations with 0 and 0.0.

    >
    > I'm guessing that you are seeing IEEE floating point behavior with
    > the floating point operations and that there isn't a perfect analog
    > to that behavior with integer operations. IEEE floating
    > point defines binary representations of negative and positive zero,
    > negative and positive infinity, and two types of NaN (not a number).
    > These 'numbers' aren't available when working with integers at the
    > machine level nor at the Ruby Fixnum or Bignum level.
    >
    > Gary Wright


    And just to underline the point... these behaviors are not ruby spec,
    but rather IEEE fp spec.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Jan 9, 2009
    #3
  4. On Jan 9, 2009, at 4:22 PM, Gary Wright wrote:

    >
    > On Jan 9, 2009, at 3:51 PM, Raphael Clancy wrote:
    >
    >> I was playing around with the basic math functions, and I had some
    >> questions about the way Ruby handles operations with 0 and 0.0.

    >
    > I'm guessing that you are seeing IEEE floating point behavior with
    > the floating point operations and that there isn't a perfect analog
    > to that behavior with integer operations. IEEE floating
    > point defines binary representations of negative and positive zero,
    > negative and positive infinity, and two types of NaN (not a number).
    > These 'numbers' aren't available when working with integers at the
    > machine level nor at the Ruby Fixnum or Bignum level.
    >
    > Gary Wright


    In particular, look at how IEEE defines operations such as 0.0/0.0

    http://steve.hollasch.net/cgindex/coding/ieeefloat.html

    -Rob

    Rob Biedenharn http://agileconsultingllc.com
    Rob Biedenharn, Jan 9, 2009
    #4
  5. Raphael Clancy, Jan 9, 2009
    #5
  6. Raphael Clancy

    Jan Dvorak Guest

    On Friday 09 January 2009 23:27:46 Raphael Clancy wrote:
    > Thanks for the quick replies (and the cool link!). I thought this might
    > be a hold over from the "good old days". ;)
    >
    > I wonder if there is any impetus to move beyond this, since I see that
    > sticking to the IEEE might cause other problems as well. (Warning,
    > grumpy blog ahead)
    >
    > http://infinitesecond.blogspot.com/2008/03/floating-point-arithmetic-bug-re
    >ports.html
    >
    > On the other hand, the effort of re-doing the whole math framework might
    > not be worth the return...


    Programming languages generally 'sticks' to IEEE 754 simply because that's
    what the hardware can do. You take the numbers and operator, pass it to the
    CPU (or more precise to CPU's math coprocessor) and you'll get output number
    (or NaN,+Inf, etc.). Doing floating point in software is possible if you really
    want to (and there are scientific libraries for precise real number
    calculations that do that), but it is not something you would *like* to do as
    common case, performance-wise.

    Jan
    Jan Dvorak, Jan 9, 2009
    #6
  7. Raphael Clancy

    Matthew Moss Guest

    On Jan 9, 2009, at 4:27 PM, Raphael Clancy wrote:
    >
    > I wonder if there is any impetus to move beyond this, since I see that
    > sticking to the IEEE might cause other problems as well. (Warning,
    > grumpy blog ahead)
    >
    > http://infinitesecond.blogspot.com/2008/03/floating-point-arithmetic-bug-reports.html


    Written by someone who does not understand floating point arithmetic.

    As Jan Dvorak indicated in another message, most languages stick to
    IEEE spec because the hardware implements the spec. And with good
    reason: it's a good spec.

    Your blogger is upset that things don't work the way he wants; perhaps
    he should create a new FP spec and implement it. I guarantee you --
    even ignoring the hardware implemented IEEE -- he won't make a
    representation as complete as IEEE.
    Matthew Moss, Jan 9, 2009
    #7
  8. I agree that the IEEE spec is closer to what the FPU is doing (actually,
    it is what the FPU is doing ;-D), and this surely gives it a speed
    advantage. But honestly, if speed was what I was after, Ruby might not
    be my first choice. Also, I'm not sure that simply being closer to the
    hardware is always a good thing. After all, I'm pretty glad that Ruby
    doesn't force me to use things like pointers or malloc(), even though
    that's much closer to how the MMU works. The IEEE spec also has one big
    strike against it, it's representation of how numbers work is (just
    slightly) wrong. It's a hold over from the days when computers couldn't
    do any better, but we can certainly do better now.

    All that being said, I can come up with several reasons why we should
    keep the IEEE spec. First, it's "traditional" and Ruby always tries to
    work in the way programmers expect it should. Second, dropping the IEEE
    spec in favor of something more mathematically correct would very likely
    break a lot of things that depend on Floats working the IEEE way. And,
    finally, who cares if the IEEE spec is broken? The number of people it
    affects is tiny, and they are likely to use higher precision math
    libraries anyway. The work needed to fix it would far out weigh the
    benefit.

    So I guess I'm all for keeping the spec, IEEE is practical, but it
    doesn't seem very "Ruby". ;-D
    --
    Posted via http://www.ruby-forum.com/.
    Raphael Clancy, Jan 10, 2009
    #8
  9. Raphael Clancy

    Klaus Stein Guest

    Raphael Clancy <> wrote:
    >
    > [...] I can come up with several reasons why we should
    > keep the IEEE spec. First, it's [ ... ]


    One important reason was not mentioned here: In floating point processing we
    have limited precision which leads to different semantics. Doing integer
    arithmetics 5 is 5, 1 is 1 and 0 is 0. In floating point arithmetics 5.0,
    1.0 and 0.0 represent an interval. See the following in irb (on a 32 bit
    Linux box):

    irb(main):007:0> 10**-200/10.0**200
    => 0.0
    irb(main):008:0> -10**-200/10.0**200
    => -0.0
    irb(main):009:0> 42.23 / (10**-200/10.0**200)
    => Infinity
    irb(main):010:0> 42.23 / (-10**-200/10.0**200)
    => -Infinity
    irb(main):011:0> (10**200/10.0**-200)
    => Infinity
    ....

    That's simply the closest we can get with limited precision.

    Floating point arithmetics _differs_ from doing math on R, and it's
    important to know this:

    irb(main):031:0> 0.1**2 == 0.01
    => false
    irb(main):032:0> 0.1**2 - 0.01
    => 1.73472347597681e-18
    irb(main):033:0> (0.1**2 - 0.01) < 1e-9
    => true

    > So I guess I'm all for keeping the spec, IEEE is practical, but it
    > doesn't seem very "Ruby". ;-D


    You could also claim floating point arithmetics is not very "Ruby2...

    Klaus
    --
    http://lapiz.istik.de/

    The Answer is 42. And I am the Answer. Now I am looking for the Question.
    Klaus Stein, Jan 10, 2009
    #9
  10. I've had a little time to think on this (and a little sleep ;-D) and I
    realize that I got sidetracked by the precision issue and it really
    isn't what bothers me. I know that precision has been the focus of most
    of the grumping about the IEEE spec, but keeping track of precision is
    part of using a computer. what bothers me it that using the IEEE spec
    causes Ruby to handle division by zero inconsistently and incorrectly.
    While the precision issue is part of the hardware, but the division by
    zero stuff is a design choice. I realize that the IEEE doesn't set out
    these specs arbitrarily and there must be many good reasons for this
    behavior. But, it seems inelegant to me.

    Like I said before, Ruby should stick with the IEEE spec, switching away
    would be a huge hassle, and the benefits would be negligible. But, that
    doesn't mean we shouldn't acknowledge that the IEEE spec has some
    issues. And that even though it's been "good enough" for long time, at
    some point in the future that could possibly change.

    Thanks for the good discussion!
    --
    Posted via http://www.ruby-forum.com/.
    Raphael Clancy, Jan 10, 2009
    #10
  11. Raphael Clancy

    Jan Dvorak Guest

    On Saturday 10 January 2009 15:23:12 Raphael Clancy wrote:
    > I've had a little time to think on this (and a little sleep ;-D) and I
    > realize that I got sidetracked by the precision issue and it really
    > isn't what bothers me. I know that precision has been the focus of most
    > of the grumping about the IEEE spec, but keeping track of precision is
    > part of using a computer. what bothers me it that using the IEEE spec
    > causes Ruby to handle division by zero inconsistently and incorrectly.
    > While the precision issue is part of the hardware, but the division by
    > zero stuff is a design choice. I realize that the IEEE doesn't set out
    > these specs arbitrarily and there must be many good reasons for this
    > behavior. But, it seems inelegant to me.


    It's still coming from the hardware, you pass fdiv(x,0.0) to FPU and you get
    floating point number back that is either NaN or Infinity. So the "design
    choice" is actually "don't do any additional checking, let the hardware handle
    it".

    I realize that other script languages are more consisent about throwing
    exception, eg. in Python:

    >>> 1.0/0.0

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    ZeroDivisionError: float division

    or Perl:
    1.0/0.0
    Illegal division by zero at - line 1.

    and the same for other operations producing NaN (eg. sqrt(-1)). I don't know
    how much of a good idea would be to follow the same way, but if you wish so,
    you can always use monkey patching to add the checks you need, eg.:

    class Float
    alias :eek:lddiv :/
    def /(y)
    if (y==0)
    raise ZeroDivisionError
    else
    self.olddiv(y)
    end
    end
    end

    p 1.0/0.0

    $ruby test.rb
    test.rb:7:in `/': ZeroDivisionError (ZeroDivisionError)
    from test.rb:14


    Jan
    Jan Dvorak, Jan 10, 2009
    #11
  12. Raphael Clancy

    Tom Link Guest

    > eg. in Python:
    > or Perl:
    > 1.0/0.0
    > Illegal division by zero at - line 1.


    What would the equivalent of the following code return in perl or
    python then?

    a = 1.0; 50.times { a /= 1_000_000_000; p 1.0 / a }

    What would you expect to be the result of:

    p 1.0 / 0.1 < 1.0 / a

    In ruby, it's true.

    Maybe it helps to think of 0.0 as 0.0 + eta with eta being too small
    to be represented, maybe not. The integer 0 is just 0 and x / 0 is not
    a number.
    Tom Link, Jan 10, 2009
    #12
  13. Raphael Clancy

    Dave Bass Guest

    I learnt a long time ago (probably in Fortran) that it's always a good
    idea to check the value of a divisor before you use it in a division.
    Now doing that comes as second nature.

    In Ruby I'd raise an exception. Or if I'm actually expecting to get a
    lot of zeroes and they're not really errors but valid data (e.g. someone
    has used them to mark incomplete data or similar) then I'd take
    appropriate action in place.

    Relying on IEEE results is likely to cause problems downstream, so it's
    best to catch these things at the earliest opportunity IMHO. (A bit like
    checking for null pointers in C.)

    Dave
    --
    Posted via http://www.ruby-forum.com/.
    Dave Bass, Jan 12, 2009
    #13
  14. Raphael Clancy

    Tom Link Guest

    > Relying on IEEE results is likely to cause problems downstream, so it's
    > best to catch these things at the earliest opportunity IMHO.


    You're probably right. This thread made me wonder though if I'd
    actually consider a division by zero error more ruby-like as the OP
    seemed to suggest. BTW in the meantime, I also checked maple and R and
    they both report 1.0/0.0 as infinity.
    Tom Link, Jan 12, 2009
    #14
  15. I think this is probably is a case of 0.0 is not really 0. After all, as
    much as I might wish it were, a float is not a real. What we really have
    is the case mentioned before, that is 0.0 is really 0 + eta, where eta
    is some very small number which represents a precision error. Earlier, I
    was thrown off by the 0.0/0.0 case, because that would really be (0 +
    eta)/(0 + eta'), and since eta and eta' have similar magnitude this
    value should be around 1, even though we can't know what the number is,
    it certainly in a number. I'm not sure why the IEEE chose to define this
    case as NaN, I think it must have been shorthand for "undefined".

    As an interesting (to nerds ;-D) aside, there are several systems in
    which 1/0 is infinity, but they usually depend on fancy geometrical
    tricks, like making the reals occupy a circle or some more complicated
    form instead of a line. So that +infinity == -infinity. That way you can
    make the function f(x)=1/x be "well" defined everywhere. I don't like
    it, but, plenty of people do...
    --
    Posted via http://www.ruby-forum.com/.
    Raphael Clancy, Jan 13, 2009
    #15
  16. On Jan 13, 2009, at 10:27 AM, Raphael Clancy wrote:

    > I think this is probably is a case of 0.0 is not really 0. After =20
    > all, as
    > much as I might wish it were, a float is not a real. What we really =20=


    > have
    > is the case mentioned before, that is 0.0 is really 0 + eta, where eta
    > is some very small number which represents a precision error.


    Actually, there are both positive 0 and negative 0 representations in =20=

    the IEEE spec. They are considered equal (-0.0 =3D=3D +0.0). I believe =
    =20
    that FORTRAN has both -0.0 and +0.0, too. There is no =CE=B5 (epsilon) =
    for =20
    0.0.

    > Earlier, I
    > was thrown off by the 0.0/0.0 case, because that would really be (0 +
    > eta)/(0 + eta'), and since eta and eta' have similar magnitude this
    > value should be around 1, even though we can't know what the number =20=


    > is,
    > it certainly in a number. I'm not sure why the IEEE chose to define =20=


    > this
    > case as NaN, I think it must have been shorthand for "undefined".


    Read the spec. There are actually two different types of NaN -- one =20
    that indicates an indeterminate value (quiet NaN or QNaN) and one that =20=

    indicates an operation is not defined (signaling NaN or SNan).

    >
    >
    > As an interesting (to nerds ;-D) aside, there are several systems in
    > which 1/0 is infinity, but they usually depend on fancy geometrical
    > tricks, like making the reals occupy a circle or some more complicated
    > form instead of a line. So that +infinity =3D=3D -infinity. That way =

    you =20
    > can
    > make the function f(x)=3D1/x be "well" defined everywhere. I don't =

    like
    > it, but, plenty of people do...
    > --=20
    > Posted via http://www.ruby-forum.com/.


    There are similar conventions that give things like 0 raised to the =20
    0th power is 1, but 0 raised to any non-zero power is 0. (You can try =20=

    that one in Ruby, too.)

    -Rob

    Rob Biedenharn http://agileconsultingllc.com
    Rob Biedenharn, Jan 13, 2009
    #16
    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. David J. Berman

    Re: HttpHandler for images and browser behavior

    David J. Berman, Jun 24, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    3,127
    David J. Berman
    Jun 24, 2003
  2. =?Utf-8?B?Z21hcnF1ZXo=?=

    Strange behavior using SSL and "FORMS" authentication.

    =?Utf-8?B?Z21hcnF1ZXo=?=, Jan 6, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    620
    Hermit Dave
    Jan 6, 2004
  3. Replies:
    0
    Views:
    429
  4. Mantorok Redgormor
    Replies:
    70
    Views:
    1,715
    Dan Pop
    Feb 17, 2004
  5. Hans Stoessel
    Replies:
    4
    Views:
    841
    Hans Stoessel
    Apr 22, 2010
Loading...

Share This Page