code to find phase angle using Math.atan()

H

harryos

while searching for code to find phase angle from real and imaginary
parts of a complex number ,I came across this snippet .It does some
quadrant correction.

double getPhaseAngle(double real,double imag){
double ang=0.0;
double pi=Math.PI;
if(imag == 0.0 && real == 0.0){ang = 0.0;}
else{ang = Math.atan(imag/real)*180.0/pi;}
if(real < 0.0 && imag == 0.0){ang = 180.0;}
else if(real < 0.0 && imag == -0.0){
ang = -180.0;}
else if(real < 0.0 && imag > 0.0){
ang += 180.0;}
else if(real < 0.0 && imag < 0.0){
ang += -180.0;}
return ang;
}

I could not understand why there is a check for imag == -0.0.
Can imaginary part ever become -0.0?Is that not the same as imag==0.0?
Is there a difference?

If someone can explain the maths in this,it would be a great help.
thanks in advance
harry.
 
A

Andreas Leitgeb

harryos said:
while searching for code to find phase angle from real and imaginary
parts of a complex number ,I came across this snippet .It does some
quadrant correction.

Have a look at: Math.atan2(double y, double x)
it does the quadrant-correction for you. (you still
need radians->degree conversion on the result, of course)

If the question was only for understanding the -0.0,
then I'll just remark that machine-arithmetics is
subtly different from "real" mathematics.
A -0.0 may come up in machine-arithmetics, when you
have a negative value that is so near to 0 that there
exists no distinct-from-zero representation for it.

It's with functions that are non-continuous at zero,
where this distinction is necessary. (in your example,
a real (or positive) zero imag with a negative real
will map to +180 degs, whereas a negative zero means
it's a tiny tiny bit below the real-axis, so you reach
it by an -180 degs phase angle.
 
L

Lew

harryos said:
while searching for code to find phase angle from real and imaginary
parts of a complex number ,I came across this snippet .It does some
quadrant correction.

Since Andreas handled your main question, I'll just comment on:
double pi=Math.PI;

A simple non-constant variable to point to a simple constant variable? What's
the point?

It can't be overweening laziness. You increased the number of characters to
type, by a bit more than an 'import static' even.
 
L

Lew

sorry,
my mistake..should have been final double.

BRAAAPPPP! Wrong.

My point was that there's no point in having a variable to stand in for variable.

Having a final double to stand in for a final double doesn't make sense either.

I ask again, since you didn't see fit to answer the first time, what was the
point?
 
G

Gavino

harryos said:
if(imag == 0.0 && real == 0.0){ang = 0.0;}
else{ang = Math.atan(imag/real)*180.0/pi;}

Doesn't this give a 'divide by zero' error if real is zero and imag is
non-zero?
 
J

Joshua Cranmer

Doesn't this give a 'divide by zero' error if real is zero and imag is
non-zero?

Floating-point arithmetic doesn't tend to give errors, only infinities
and NaNs.

0.0/0.0 = NaN
1.0/0.0 = Infinity
-1.0/0.0 = -Infinity
 
R

Roedy Green

I could not understand why there is a check for imag == -0.0.
Can imaginary part ever become -0.0?Is that not the same as imag==0.0?
Is there a difference?

public class ZeroTest
{
public static void main (String[] args)
{
// prints true. -0 and +0 are considered equal
System.out.println( 0.0d == -0.0d );
}
}
 
L

Lew

harryos wrote, quoted or indirectly quoted someone who said :
Roedy said:
public class ZeroTest
{
public static void main (String[] args)
{
// prints true. -0 and +0 are considered equal
System.out.println( 0.0d == -0.0d );
}
}

That behavior is required by
<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.20.1>
and
<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.21.1>
It shows that the snippet the OP quoted is flawed and will not give the
results it implicitly promises.

That method also is flawed in that it yields a range of
"[ -180.0, 180.0 ]" (degrees). One end of that range needs to be excluded.
Conventionally we use ranges closed on the low end and open at the high, thus
"[ -180.0, 180.0 )". Had the cited code done that it wouldn't be foolishly
and incorrectly attempting to distinguish positive zero from negative.

Comparison to zero is a special case, but in general one should be wary of
'==' comparisons with floating-point values ('float' or 'double'). One
technique instead of comparing two values for equality is to test if the
difference is less than an epsilon:

boolean closeEnough =
(Math.abs( a - b ) < Double.MIN_NORMAL);

Consider also:

public static void main( String[] args )
{
// prints true. -0 and +0 are considered equal
System.out.print( "0.0d == -0.0d? " );
System.out.println( 0.0d == -0.0d );

System.out.print(
"(Math.sqrt( 0.1 ) * Math.sqrt( 0.1 )) == 0.1 ? " );
System.out.println(
(Math.sqrt( 0.1 ) * Math.sqrt( 0.1 )) == 0.1 );

System.out.print(
"(Math.sqrt( 0.01 ) * Math.sqrt( 0.01 )) == 0.01? " );
System.out.println(
(Math.sqrt( 0.01 ) * Math.sqrt( 0.01 )) == 0.01 );
}

Output:

0.0d == -0.0d? true
(Math.sqrt( 0.1 ) * Math.sqrt( 0.1 )) == 0.1 ? true
(Math.sqrt( 0.01 ) * Math.sqrt( 0.01 )) == 0.01? false
 
A

Andreas Leitgeb

Lew said:
That method also is flawed in that it yields a range of
"[ -180.0, 180.0 ]" (degrees). One end of that range needs to be excluded.

While the specified code has the implementation flaws you described (and
which I missed in my previous look at it), it was *designed* to really
yield a both-ends-included range of [-180.0, 180.0].

If you read the docu of Math.atan2, you'd notice that it also yields
a closed range:

" # If the first argument is positive zero and the second argument is
" negative, or [...], then the result is the double value closest to pi.
" # If the first argument is negative zero and the second argument is
" negative, or [...], then the result is the double value closest to -pi.
 
A

Andreas Leitgeb

Patricia Shanahan said:
Thomas said:
According to Andreas Leitgeb said:
If you read the docu of Math.atan2, you'd notice that it also yields
a closed range:
" # If the first argument is positive zero and the second argument is
" negative, or [...], then the result is the double value closest to pi.
" # If the first argument is negative zero and the second argument is
" negative, or [...], then the result is the double value closest to -pi.
Arguably, Math.atan2() cannot yield a closed range because pi cannot be
represented exactly in a double.

I didn't even specify any particular range in my claim, except that it is
closed.
It does yield a closed range, [-Math.PI, Math.PI].

That was the range I had in mind. Or more verbosely and more directly
adhering to the Math.atan2 description:
[ the double value closest to -pi, the double value closest to pi ]

PS: http://xkcd.com/386/ :)
 
S

Stefan Ram

Thomas Pornin said:
According to Patricia Shanahan said:
It does yield a closed range, [-Math.PI, Math.PI].
Duh. There's nothing such as an open range in a finite computer; in

In C, the precision (size) of a double value is
implementation specified, so one can have (in C):

int a( int const double x ){ return 0. <= x && x <= 1.; }

versus

int b( int const double x ){ return 0. < x && x < 1.; }

. Given a( x ), we can not generally say in an
implementation-independent manner whether b( x ),
while the limits »0.« and »1.« of »a« and »b« are the same.

Therefore we can not find double values »u« and »w« so that,
given

int c( int const double x ){ return 0. <= u && x <= w; }

, c( x )== b( x ) will always be true for every
implementation of the programming language C.

Thus, there is some kind of difference between »a« and »b«
that might be named by some wording, and someone might be
inclined to use »closed« versus »open«, while the meaning
is not the same as for intervals of real numbers.
 
A

Andreas Leitgeb

Thomas Pornin said:
According to Patricia Shanahan said:
It does yield a closed range, [-Math.PI, Math.PI].
Duh. There's nothing such as an open range in a finite computer
That wasn't my point, nor was it Patricia's (afaict)
The discussion was about a function which returned an angle in degree
(that is a value which makes sense only modulo 360) and that the said
function could return either 180 or -180, which have the same meaning
(since 180 = -180 + 360). I was pointing out that with Math.atan2()
and more generally with radians, such a situation cannot occur, since
it is not possible to have two distinct 'double' values which are
equal when reduced modulo pi.

Well, it *is* possible. if you scaled atan2's return value to degrees,
you'd get *exactly*(if scaling is done correctly) [-180,180], to account
for the possibility of positive and negative zeroes.
 
D

Dr J R Stockton

In comp.lang.java.programmer message <hq0oh5h1toh0t4sr87s6blnt2n0b836dcg
@4ax.com>, Sun, 6 Dec 2009 11:17:49, Roedy Green <[email protected]
om.invalid> posted:
public class ZeroTest
{
public static void main (String[] args)
{
// prints true. -0 and +0 are considered equal
System.out.println( 0.0d == -0.0d );
}
}

But the reciprocals of +0 and -0 may well be unequal. If do, it can be
useful (occasionally) to be aware that, for any X, (X + 1/X) has the
same sign as X and cannot be zero.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top