atan2 not consisent

37 visualizaciones (últimos 30 días)
Richard Bag
Richard Bag el 24 de Nov. de 2020
Comentada: Paul el 6 de Dic. de 2020
I have the following values that I run through the atan2 function:
a(77:78,:)
ans =
-0.250000000000000 0 -0.950000000000000
-0.260000000000000 0 -0.950000000000000
when I put the above array through the atan2 function, the first value is positive and the second is negative,
atan2(a(77:78,2),a(77:78,3))
ans =
3.141592653589793
-3.141592653589793
If I type in each value of the second row of data by hand, the result is differnt for the atan2 function (it is positive):
atan2(0,-0.95)
ans =
3.141592653589793
If I build a test matrix, manually inputing the values, the atan2 results are both positive.
test = [-0.25, 0 , -0.95; -0.26, 0 , -0.95]
test =
-0.250000000000000 0 -0.950000000000000
-0.260000000000000 0 -0.950000000000000
>> atan2(test(1,2),test(1,3))
ans =
3.141592653589793
>> atan2(test(2,2),test(2,3))
ans =
3.141592653589793
Question: Why are the values of atan2 function positive and negative in the first case but then both positive when I type out the values?
Aside: If done separately:
atan2(a(77,2),a(77,3))
ans =
3.141592653589793
>> atan2(a(78,2),a(78,3))
ans =
-3.141592653589793
Thank you

Respuesta aceptada

Stephen23
Stephen23 el 25 de Nov. de 2020
Editada: Stephen23 el 25 de Nov. de 2020
The reason is a little arcane: negative zero:
The other answers and comments are wrong: this has nothing to do with floating point error or "almost zero" values.
The second column values are exactly zero, and we know that the value is exactly zero because in both long and short format only the exact value zero is displayed as one single digit "0", just as all of your examples show.
So what is the catch?
The catch is simply the IEEE 754 defines two zeros, a positive zero and a negative zero. Same value, different signs. Some (but not all) operations retain the sign when operating on them.
One of your zeros is negative and one is positive, but unfortunately MATLAB** displays them without the sign:
Y = [0;-0] % positive and negative zero!
Y = 2×1
0 0
X = [-0.95;-0.95]; % these values are not really relevant
atan2(Y,X)
ans = 2×1
3.1416 -3.1416
Here is a useful trick to detect if a zero is positive or negative (simply displaying it doesn't work):
Y % they look the same ... but are they?
Y = 2×1
0 0
sign(1./Y) % no!
ans = 2×1
1 -1
Negative zeros can be generated by some arithmetic operations, or perhaps by converting data from text. If you want to remove negative zeros from an array without changing the sign of the other data, just add zero:
Z = [-0,-2,+0,3]
Z = 1×4
0 -2 0 3
sign(1./Z)
ans = 1×4
-1 -1 1 1
Z = 0+Z % remove negative zeros
Z = 1×4
0 -2 0 3
sign(1./Z)
ans = 1×4
1 -1 1 1
** for what it's worth, Octave does display the sign.
  8 comentarios
Bruno Luong
Bruno Luong el 6 de Dic. de 2020
Editada: Bruno Luong el 6 de Dic. de 2020
>> format hex
>> x = round([0+1i*3; -0.1-0.1*1i])
x =
0000000000000000 4008000000000000i
8000000000000000 8000000000000000i
>> x+complex(0)
ans =
0000000000000000 4008000000000000i
0000000000000000 0000000000000000i
Beside that ATAN2 accepts only real arguments. So not sure this observation is relevant here, and I could't locate the upstream quote.
Paul
Paul el 6 de Dic. de 2020
The upstream quote is in Stephen's original answer.
Wasn't making the observation in the context of ATAN2 alone; was just interested in how to get rid of the negative zero in general.
Adding complex(0) is a much better solution. Thanks for pointing that out.

Iniciar sesión para comentar.

Más respuestas (2)

John D'Errico
John D'Errico el 24 de Nov. de 2020
What you don't understand is that just because MATLAB displays a number represented to 15 digits, does not mean it is EXACTLY the same thing as what you typed in.
In fact, typically when MATLAB shows a number as -0.950000000000000, you should expect there is more to that number than meets the eye. Anyway, a double precision number cannot represent the number you have written exactly. Just as you cannot represent the fraction 2/3 exactly in any finite number of decimal digits, you cannot represent the decimal number 0.95 as an exact binary representation. This number would be represented by the infinitely repeating string...
'11110011001100110011001100110011001100110011001100110...'
So when you typed in 0.95, you certainly were typing in a DIFFERENT number than you havd stored in the array a. And that is why you get a differnt result. It is not atan2, but the numbers you passed to atan2.
  10 comentarios
Bruno Luong
Bruno Luong el 25 de Nov. de 2020
Editada: Bruno Luong el 25 de Nov. de 2020
For sure
a(145,2)
is negative (but close to 0)
Stephen23
Stephen23 el 25 de Nov. de 2020
Editada: Stephen23 el 25 de Nov. de 2020
"I suspect the values are not exact 0, and that fact is being hidden by your use of format short"
@Walter Roberson: can you please show a one single example of a non-zero value that is displayed as the single digit "0" (as all of Richard Bag's second-column examples in this thread show). I can't find any:
>> format short
>> [0,eps(0),-eps(0),-0.95]
ans =
0 0.0000 -0.0000 -0.9500
>> format long
>> [0,eps(0),-eps(0),-0.95]
ans =
0 0.000000000000000 -0.000000000000000 -0.950000000000000

Iniciar sesión para comentar.


Bruno Luong
Bruno Luong el 25 de Nov. de 2020
Editada: Bruno Luong el 25 de Nov. de 2020
Your result
atan2(a(77:78,2),a(77:78,3))
ans =
3.141592653589793
-3.141592653589793
Type single value
a(78,2)
you will see it's actually negative (not exactly 0).
Yes atan2(y,x) has discontinuity at the semi axes { y = 0 } for x < 0.
  4 comentarios
Bruno Luong
Bruno Luong el 25 de Nov. de 2020
Editada: Bruno Luong el 25 de Nov. de 2020
Got you stephen. Good point
Walter Roberson
Walter Roberson el 25 de Nov. de 2020
Ah, matlab does consider the sign of the 0 in deciding quadrant.

Iniciar sesión para comentar.

Categorías

Más información sobre Logical en Help Center y File Exchange.

Productos


Versión

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by