3

I cannot figure out why division by 0 gives different results in the following two cases. amort is a function that calculates a constant amortization schedule. The only thing we care about now is that the last element of A is exactly 0.

amort = @(r,M) ((1+r).^(0:M)' - (1+r).^M) ./ (1-(1+r).^M)

A = amort(0.03, 20);

>> A(end)==0
ans =
     1

What looks strange is the following:

>> 1/0
ans =
   Inf
>> 1/A(end)
ans =
  -Inf

However

>> sign(A(end))
ans =
     0
>> 1/abs(A(end))
ans =
   Inf

How is this possible and why? Is there some kind of hidden "sign"?

Giuseppe
  • 518
  • 10
  • 22
  • 1
    Possible duplicate of [Why does Gnu Octave have negative zeroes?](http://stackoverflow.com/questions/2109755/why-does-gnu-octave-have-negative-zeroes) – sco1 Nov 29 '16 at 18:27
  • While the duplicate references Octave, the accepted answer deals with MATLAB and the IEEE-754 format. – sco1 Nov 29 '16 at 18:28
  • 1
    `A(end)` is negative zero. `fprintf('%f\n', A(end))` returns `-0.000000` – sco1 Nov 29 '16 at 18:28

1 Answers1

6

A(end) actually has it's sign bit set (i.e. it is negative zero). Try using num2hex to see the hex representation:

>> a = -0
a =
     0    % Note the sign isn't displayed

>> num2hex(A(end))
ans =
8000000000000000

>> num2hex(a)
ans =
8000000000000000  % Same as above

>> num2hex(0)
ans =
0000000000000000  % All zeroes

>> 1/a
ans =
  -Inf

Notice that a -0 is displayed as 0, but in reality has its sign bit set. Hence the -Inf result.

Also note this explanation of the sign function (emphasis mine):

For each element of X, sign(X) returns 1 if the element is greater than zero, 0 if it equals zero and -1 if it is less than zero.

Since -0 isn't less than zero, but instead equal to 0, sign returns 0.

gnovice
  • 125,304
  • 15
  • 256
  • 359
  • I see - this is useful. Any guess why the sign bit is set to zero then? Does it depend on machine precision/approximation in performing the calculations requested by `amort` ? Can I prevent these situations? – Giuseppe Nov 29 '16 at 19:05
  • 2
    @Giuseppe: In the `amort` function in your example, the numerator for the last vector element will be 0 but the denominator will be `(1-1.03^20)`, or about -0.8061. Dividing 0 by a negative number gives you -0. If you swap the terms in both the numerator and denominator (i.e. multiply through by -1 on top and bottom) you can avoid it. – gnovice Nov 29 '16 at 19:15