Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we have 0.0 and -0.0 in Ruby? [duplicate]

In ruby why can I assign a negative sign to 0.0 float, is this feature useful in any way? Could someone explain this one to me?

-0.0 #=> -0.0  -0.0 * -1 #=> 0.0 
like image 561
Bruno Alexandre Moreira Pincho Avatar asked Nov 04 '19 10:11

Bruno Alexandre Moreira Pincho


People also ask

How much faster is Ruby on the NES compared to Ruby?

With Optcarrot benchmark, which measures single thread performance based on NES’s game emulation workload, it achieved 3x faster performance than Ruby 2.0! . was used as Ruby 3.0.

Is this the end of Ruby?

Ruby3.0 is a milestone. The language is evolved, keeping compatibility. But it’s not the end. Ruby will keep progressing, and become even greater. Stay tuned! — Matz Merry Christmas, Happy Holidays, and enjoy programming with Ruby 3.0! Ruby was first developed by Matz (Yukihiro Matsumoto) in 1993 and is now developed as Open Source.

Is Ruby 3x3 faster than Ruby 2?

Especially about performance, Matz stated “Ruby3 will be 3 times faster than Ruby2” a.k.a. Ruby 3x3. With Optcarrot benchmark, which measures single thread performance based on NES’s game emulation workload, it achieved 3x faster performance than Ruby 2.0!

What is the goal of Ruby 3?

From 2015 we developed hard toward Ruby 3, whose goal is performance, concurrency, and Typing. Especially about performance, Matz stated “Ruby3 will be 3 times faster than Ruby2” a.k.a. Ruby 3x3.


2 Answers

You can assign a negative sign to a 0.0 float in Ruby because all IEEE 754 floating point numbers have a sign bit to indicate whether the number is positive or negative.

Here are the binary representations of 2.5 and -2.5:

[2.5].pack('f').unpack1('b*') #=> "00000000000000000000010000000010"  [-2.5].pack('f').unpack1('b*') #=> "00000000000000000000010000000011" 

The last bit is the sign bit. Note that all the other bits are identical.

On the other hand, there is zero with a sign bit of 0:

['00000000000000000000000000000000'].pack('b*').unpack1('f') #=> 0.0 

and zero with a sign bit of 1:

['00000000000000000000000000000001'].pack('b*').unpack1('f') #=> -0.0 

Although 0.0 and -0.0 are numerically equal, they are not identical on the object level:

(0.0).eql?(-0.0)   #=> true (0.0).equal?(-0.0) #=> false 

Negative zeros have some special properties. For instance:

1 / 0.0    #=> Infinity 1 / -0.0   #=> -Infinity 

Assigning - explicitly is not the only way to get -0.0. You may also get -0.0 as the result of a basic arithmetic operation:

-1.0 * 0 #=> -0.0 
like image 123
Stefan Avatar answered Oct 23 '22 23:10

Stefan


Mathematical operations have real-number results, but we map those real results onto the nearest floating-point number, which is called "rounding". For every floating-point number, there is a range of real numbers that will round to that float, and sometimes it's useful to think of the float as being identified with that range of real numbers.

Since there is a finite supply of floating-point numbers, there must be a smallest positive float, and its opposite, the smallest (magnitude) negative float. But what happens to real number results even smaller than those? Well, they must "round to zero". But "a really small number greater than zero" and "a really small number less than zero" are pretty different things with pretty different mathematical behavior, so why should we lose the distinction between them, just because we're rounding? We don't have to.

So, the float 0 doesn't just include the real number 0, it also includes too-small-to-represent positive quantities. And the float -0 includes too-small-to-represent negative quantities. When you use them in arithmetic, they follow rules like "negative times positive equals negative; negative times negative equals positive". Even though we've forgotten almost everything about these numbers in the rounding process, we still haven't forgotten their sign.

like image 22
hobbs Avatar answered Oct 23 '22 23:10

hobbs