rubyfloating-pointnegative-zero

Why do we have 0.0 and -0.0 in Ruby?


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

Solution

  • 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