Floating point numbers have one bit that is used to designate sign, and this bit applies when the value of the number is zero. This is called "signed zero". MATLAB hides this very well in most situations, but it does pop up in certain cases. Recently this came up in a question on Stack Overflow involving complex numbers initialization.
Example
Below is a demonstration of how one complex number initialization syntax can inadvertently create a signed zero.
Create two complex numbers, a and b. The intent it that both variables have the value (0, -1).
>> a = 0-j;
>> b = -j;
Extract the real component and verify that they are 0, and that they are "equal".>> ra = real(a)
ra =
0
>> rb = real(b)
rb =
0
>> ra==0
ans =
1
>> isequal(ra,rb)
ans =
1
But it's clear they are not equal with this operation:>> 1/ra
ans =
Inf
>> 1/rb
ans =
-Inf
Interesting. Why does rb clearly have a sign associated with it even though it is not visisble?Explanation
Well, as it turns out MATLAB's isequal does not check the sign bit when the value is zero! In this example, with
b
we set the sign bit for both the real and imaginary parts when we call -j = -complex(0,1)
instead of a = 0-j
which is equal to complex(0,-1)
(more information at Creating Complex Numbers). The difference can only be seen by inspecting the data at a bit level. In MATLAB, it's best to use typecast
, which does no conversion of the underlying data:>> dec2bin(typecast(ra,'uint64'),64)
ans =
0000000000000000000000000000000000000000000000000000000000000000
>> dec2bin(typecast(rb,'uint64'),64)
ans =
1000000000000000000000000000000000000000000000000000000000000000
The 1 leading the second result is bit #63 in the IEEE 754 double precision floating point representation:
>> dec2bin(typecast(-0,'uint64'),64)
ans =
1000000000000000000000000000000000000000000000000000000000000000
Summary
2 comments:
Very good explanation!
Thanks, Luis. I'm not planning to re-post my favorite SO posts, but this one seemed especially obscure and interesting to me.
Post a Comment