Search code examples
matlabfloating-pointcomplex-numberszero

Do variables contain extra hidden metadata - aka When is zero not zero (but still is)


I hate having to ask this because I assume the answer must be simple, but I cannot for the life of me seem to track down the source. While trying to rewrite a function I ran across this problem:

a = -j
x = real(a)  
y = imag(a)
y/x

Which spits out Inf, unexpectedly for me. However...

a = 0
b = -1
b/a

returns -Inf, like I would expect. Inquiring further, a == x, b == y. Clearly that isn't true however. I finally tracked down the problem to this after a lot of frustration. If the original input for a is instead 0-j (vs. -j) then there is no problem.

Both real(-j) and real(0-j) return zero and test as zero, but obviously seem to retain some metadata relating to their origin that I absolutely cannot discover. What precisely am I missing here? It will feel downright wrong if I have to solve this with something like if (x == 0) then x = 0;


Solution

  • Not metadata, just the sign bit of the double precision float.

    >> a = 0-j;
    >> b = -j;
    >> ra = real(a)
    ra =
         0
    >> rb = real(b)
    rb =
         0
    >> ra==0
    ans =
         1
    >> isequal(ra,rb)
    ans =
         1
    

    Looks the same so far. However, the difference is that with b, we set the sign bit for both the real and imaginary parts when we do -j = -complex(0,1) vs. 0-j = complex(0,-1) (see Creating Complex Numbers). Looking deeper with typecast, which does no conversion of the underlying data:

    >> dec2bin(typecast(ra,'uint64'),64)
    ans =
    0000000000000000000000000000000000000000000000000000000000000000
    >> dec2bin(typecast(rb,'uint64'),64)
    ans =
    1000000000000000000000000000000000000000000000000000000000000000
    

    That 1 is bit 63 (of 0) in the IEEE 754 double precision floating point representation:

    enter image description here

    Voila! -0 exists in MATLAB too!