Forum: Ruby Detecting -0.0

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Da33a4ac652c1c8900392a8599206640?d=identicon&s=25 Thomas B. (tpreal)
on 2009-04-28 22:07
Hello.

I have a simple question - how to detect if a variable contains a Float
of value -0.0? Is there any special method for this, or any comparison
that distinguishes negative zero from a the regular zero?

Thanks in advance.
TPR.
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-04-28 22:13
(Received via mailing list)
Thomas B. wrote:
> Hello.
>
> I have a simple question - how to detect if a variable contains a Float
> of value -0.0? Is there any special method for this, or any comparison
> that distinguishes negative zero from a the regular zero?
>
> Thanks in advance.
> TPR.

irb(main):001:0> x = -0.0
=> -0.0
irb(main):002:0> x == 0.0
=> true
irb(main):003:0> x.eql?(0.0)
=> true
irb(main):004:0> x.equal?(0.0)
=> false
09348009e57e24e10bbc08d925bf69ca?d=identicon&s=25 Matthias Reitinger (reima)
on 2009-04-28 22:14
Thomas B. wrote:
> I have a simple question - how to detect if a variable contains a Float
> of value -0.0? Is there any special method for this, or any comparison
> that distinguishes negative zero from a the regular zero?

  irb(main):001:0> 1/-0.0 < 0
  => true
  irb(main):002:0> 1/0.0 < 0
  => false

-Matthias
09348009e57e24e10bbc08d925bf69ca?d=identicon&s=25 Matthias Reitinger (reima)
on 2009-04-28 22:17
Joel VanderWerf wrote:
> Thomas B. wrote:
>> Hello.
>>
>> I have a simple question - how to detect if a variable contains a Float
>> of value -0.0? Is there any special method for this, or any comparison
>> that distinguishes negative zero from a the regular zero?
>>
>> Thanks in advance.
>> TPR.
>
> irb(main):001:0> x = -0.0
> => -0.0
> irb(main):002:0> x == 0.0
> => true
> irb(main):003:0> x.eql?(0.0)
> => true
> irb(main):004:0> x.equal?(0.0)
> => false

  irb(main):001:0> x = 0.0
  => 0.0
  irb(main):002:0> x == 0.0
  => true
  irb(main):003:0> x.eql?(0.0)
  => true
  irb(main):004:0> x.equal?(0.0)
  => false

In short: you cannot distinguish between 0.0 and -0.0 this way.

-Matthias
Da33a4ac652c1c8900392a8599206640?d=identicon&s=25 Thomas B. (tpreal)
on 2009-04-28 22:25
Thank you :)

Joel,
your answer is not very helpful as 0.0.equals?(0.0) also returns false.

Matthias,
>   irb(main):001:0> 1/-0.0 < 0
>   => true
>   irb(main):002:0> 1/0.0 < 0
>   => false
thanks, that's just the obvious thing that I have overlooked! Changing
the difference between zeros to the difference between infinities.

TPReal.
149379873fe2cb70e550c6bff8fedd0c?d=identicon&s=25 Jeff Schwab (Guest)
on 2009-04-28 22:26
(Received via mailing list)
Joel VanderWerf wrote:
> irb(main):001:0> x = -0.0
> => -0.0
> irb(main):002:0> x == 0.0
> => true
> irb(main):003:0> x.eql?(0.0)
> => true
> irb(main):004:0> x.equal?(0.0)
> => false

What does that accomplish?

irb(main):001:0> (-0.0).equal? -0.0
=> false
149379873fe2cb70e550c6bff8fedd0c?d=identicon&s=25 Jeff Schwab (Guest)
on 2009-04-28 22:30
(Received via mailing list)
Thomas B. wrote:
> Hello.
>
> I have a simple question - how to detect if a variable contains a Float
> of value -0.0? Is there any special method for this, or any comparison
> that distinguishes negative zero from a the regular zero?

NB: I'm not sure how portable this is.

def negative_zero?(number)
   inverse = 1 / number.to_f
   inverse < 0 && inverse.infinite? ? true : false
end

[ 0.0, # false
  -0.0, # true
  -1.0, # false
   1.0  # false
].each do |f|
   puts negative_zero?(f)
end
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-04-28 22:36
(Received via mailing list)
Jeff Schwab wrote:
>>
>
> irb(main):001:0> (-0.0).equal? -0.0
> => false

Oops. That never seemed right to me. Float#equal? should hide the fact
that floats are allocated, and not immediate.

It has always seemed like a leaky abstraction this way.
7a561ec0875fcbbe3066ea8fe288ec77?d=identicon&s=25 Sebastian Hungerecker (Guest)
on 2009-04-28 22:43
(Received via mailing list)
Joel VanderWerf wrote:
> Oops. That never seemed right to me. Float#equal? should hide the fact
> that floats are allocated, and not immediate.

Why would it? It doesn't do it for any other type of object. And if it
would,
what would be the difference to == ?
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-04-28 23:00
(Received via mailing list)
Sebastian Hungerecker wrote:
> Joel VanderWerf wrote:
>> Oops. That never seemed right to me. Float#equal? should hide the fact
>> that floats are allocated, and not immediate.
>
> Why would it? It doesn't do it for any other type of object. And if it would,
> what would be the difference to == ?

Because it is only a quirk of cpu architecture that forces them to be
allocated rather than immediate. Maybe some future ruby implementation
(on >32 bit systems) will use immediate double-precision floats. Other
types will never be immediate.

The difference to #== would be the same as today: #== performs numeric
type conversions (and consequently erases the difference between 0.0 and
-0.0). But #equal? never would.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-28 23:55
(Received via mailing list)
On 28.04.2009 22:27, Jeff Schwab wrote:
>   inverse = 1 / number.to_f
>   inverse < 0 && inverse.infinite? ? true : false

Why do you use the ternary operator to convert a boolean into a boolean?

> end
>
> [ 0.0, # false
>  -0.0, # true
>  -1.0, # false
>   1.0  # false
> ].each do |f|
>   puts negative_zero?(f)
> end

My 0.02 EUR: normally there should not be any distinction between 0.0
and -0.0.  Even though computer math is not the same as real math, the
distinction does not seem to make sense to me.

Kind regards

  robert
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2009-04-29 00:40
(Received via mailing list)
On Apr 28, 2009, at 4:59 PM, Joel VanderWerf wrote:

> implementation (on >32 bit systems) will use immediate double-
> precision floats. Other types will never be immediate.

A quick look at the IEEE format suggests that there are (2^51 - 1) bit
patterns that are all considered NaN (not a number).

Seems like it might be possible to encode Ruby references in there.

Does anyone know of a language implementation that tags references in
that way?


Gary Wright
9e2504e0b74e5384af09ce8a660afac4?d=identicon&s=25 Pascal J. Bourguignon (Guest)
on 2009-04-29 01:20
(Received via mailing list)
Gary Wright <gwtmp01@mac.com> writes:
> [...]
> A quick look at the IEEE format suggests that there are (2^51 - 1) bit
> patterns that are all considered NaN (not a number).
>
> Seems like it might be possible to encode Ruby references in there.
>
> Does anyone know of a language implementation that tags references in
> that way?

Some specific NaN are produced by arithmetic operations.
Does IEEE forbid a FP unit to generate any NaN for some operations?

It would seem to me to be dangerous to be able to produce random
references from arithmetic operations...
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-04-29 03:11
(Received via mailing list)
Pascal J. Bourguignon wrote:
> Some specific NaN are produced by arithmetic operations.
> Does IEEE forbid a FP unit to generate any NaN for some operations?
>
> It would seem to me to be dangerous to be able to produce random
> references from arithmetic operations...

The interpreter would have to add code to check for that and replace
with some canonical NaN that doesn't conflict.

The ruby runtime already has to call rb_float_new() on the result of
every floating point function. Doing this check instead would be less
overhead.
149379873fe2cb70e550c6bff8fedd0c?d=identicon&s=25 Jeff Schwab (Guest)
on 2009-04-29 17:48
(Received via mailing list)
Robert Klemme wrote:
>> def negative_zero?(number)
>>   inverse = 1 / number.to_f
>>   inverse < 0 && inverse.infinite? ? true : false
>
> Why do you use the ternary operator to convert a boolean into a boolean?

I don't.  Float#infinite? can return nil, -1, or +1, but never true or
false. Without the ternary, the original client code produces the
following, far less meaningful output, including the blank line:

false
-1

false

>> end
>>
>> [ 0.0, # false
>>  -0.0, # true
>>  -1.0, # false
>>   1.0  # false
>> ].each do |f|
>>   puts negative_zero?(f)
>> end

> My 0.02 EUR: normally there should not be any distinction between 0.0
> and -0.0.  Even though computer math is not the same as real math, the
> distinction does not seem to make sense to me.

"Real" math?  Whatever you say.  In EE college courses, professors often
use -0 to represent the limit of an asymptotic function that approaches
zero from the negative side, e.g. the voltage decay of a negatively
charged capacitor.  The use has nothing to do with computers or IEEE
floats.

Anyway, take it up with the OP; AFAIK, his question was academic, but
maybe he has an interesting use case.
Da33a4ac652c1c8900392a8599206640?d=identicon&s=25 Thomas B. (tpreal)
on 2009-04-29 19:05
Jeff Schwab wrote:
> "Real" math?  Whatever you say.  In EE college courses, professors often
> use -0 to represent the limit of an asymptotic function that approaches
> zero from the negative side, e.g. the voltage decay of a negatively
> charged capacitor.  The use has nothing to do with computers or IEEE
> floats.
>
> Anyway, take it up with the OP; AFAIK, his question was academic, but
> maybe he has an interesting use case.

In fact, the -0.0 in programming is not very similar to the real math
lim_{x->0-}(x). The simplest proof of this is the fact that -(1.0-1.0)
gives -0.0, while after pushing the minus into the parenthesis we get
-1.0+1.0 which gives 0.0. So I wouldn't say that -0.0 resembles the
limes of capacitor charge, maybe only a bit. But if we wanted some more
real math logic, we would need also +0.0 (different from 0.0), begin the
result of 1.0/infinity. Then we would have -(+0.0) = -0.0, but -(0.0) =
0.0. But still it's only some approximation of "real math".

Because of these inconsistency in IEEE (inconsistency with the real math
or physics, I mean, not in IEEE itself), I'm not trying to use -0.0 as a
real limes of something. The real use case is as follows (if anybody
should be interested):

A car can drive forward or reverse, but after it brakes to stop after,
say, going forward, it needs to spend a short time staying still before
it can start going backwards. This is a way of modelling the time needed
to switch the gear from 1 and R (and the same applies to switching from
R to 1). So now if I'm controlling the car, then I should be able to
give it the desired velocity (the set point to a controller). So I
decided that 0.0 means "don't move and be ready to go forward
immediately (while I know there will be a moment's pause if I want to go
backwards now)", while -0.0 means "don't move but stay switched to
reverse, so that there's no time needed to start driving reverse (while
a moment will be needed should I decide to go forward)". That's it, just
one more bit of information pushed into the value of zero, which is
exactly where I need it.

TPR.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-29 21:36
(Received via mailing list)
On 29.04.2009 17:39, Jeff Schwab wrote:
>>>
> false
> -1
>
> false

Well, but all these are perfectly boolean values in Ruby.  There is no
need to convert the expression other than for display maybe.  But in
that case I'd do the conversion outside the method as it does not add
any semantics to the method implementation but costs time.

Kind regards

  robert
149379873fe2cb70e550c6bff8fedd0c?d=identicon&s=25 Jeff Schwab (Guest)
on 2009-04-29 23:11
(Received via mailing list)
Robert Klemme wrote:
>>>>
>> following, far less meaningful output, including the blank line:
>>
>> false
>> -1
>>
>> false
>
> Well, but all these are perfectly boolean values in Ruby.

They can be used seamlessly in boolean contexts, but that does not make
them boolean values in the sense that true and false are.

> There is no
> need to convert the expression other than for display maybe.

You mean, like, maybe in a Usenet post?

> But in
> that case I'd do the conversion outside the method as it does not add
> any semantics to the method implementation but costs time.

Have you done enough profiling to demonstrate that there is in fact a
performance penalty, and that it justifies adding complexity to the
client code?  Silliness.  Let the function return consistent,
predictable values, and quit your whining.
D0ac5c9608854166a5483061a169405e?d=identicon&s=25 snex (Guest)
on 2009-04-30 02:10
(Received via mailing list)
On Apr 28, 3:07 pm, "Thomas B." <tpr...@gmail.com> wrote:
> Hello.
>
> I have a simple question - how to detect if a variable contains a Float
> of value -0.0? Is there any special method for this, or any comparison
> that distinguishes negative zero from a the regular zero?
>
> Thanks in advance.
> TPR.
> --
> Posted viahttp://www.ruby-forum.com/.

shouldnt converting it to a String and then testing for the presence
of '-' work?
This topic is locked and can not be replied to.