[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Behavior of 0 and 0.0...

Raphael Clancy

1/9/2009 8:52:00 PM

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

15 Answers

Gary Wright

1/9/2009 9:22:00 PM

0

[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




Joel VanderWerf

1/9/2009 9:25:00 PM

0

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

Rob Biedenharn

1/9/2009 9:26:00 PM

0


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

-Rob

Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com



Raphael Clancy

1/9/2009 10:28:00 PM

0

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

On the other hand, the effort of re-doing the whole math framework might
not be worth the return...
--
Posted via http://www.ruby-....

Jan Dvorak

1/9/2009 11:10:00 PM

0

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


Matthew Moss

1/9/2009 11:23:00 PM

0


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

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.


Raphael Clancy

1/10/2009 4:14:00 AM

0

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

Klaus Stein

1/10/2009 9:12:00 AM

0

Raphael Clancy <raphael.clancy@gmail.com> 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...

The Answer is 42. And I am the Answer. Now I am looking for the Question.

Raphael Clancy

1/10/2009 2:23:00 PM

0

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

Jan Dvorak

1/10/2009 3:16:00 PM

0

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 :olddiv :/
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