Unexpected answer returned by Math.sin

Hi all, I’m just wondering why the following isn’t producing the answer 0 as a sine wave normally be at when it reaches 180 degrees. Can anyone see why?

System.out.println(Math.sin(Math.toRadians(180.0)));

Thanks

Math.toRadians(180.0) returns PI. PI cannot be accurately described in any base (except products of pi).


	Math.sin(Math.toRadians(180.0)) == Math.sin(Math.PI) != 0.00;

Because:


        Math.PI != pi

We can verify that Math.PI is indeed the best approximation of PI:


			System.out.println(Math.sin(Math.PI - Math.ulp(Math.PI)));
			System.out.println(Math.sin(Math.PI));
			System.out.println(Math.sin(Math.PI + Math.ulp(Math.PI)));

Thanks for the reply! Ah ok, I see. Is there any way around this problem?

Is it really a problem?

Well the code snippet above seems to return 1.2246467991473532E-16 rather than 0. Is that typically an acceptable margin of error?

Note the ‘e-16’

1.2246467991473532E-16
equals
0.00000000000000012246467991473532

Ah, that’s fine then. :slight_smile: Is there an easy way to convert that to that readable format in Java? Just for testing

Type cast it to an integer.

That’s great. Thanks for the help. :slight_smile:

I wouldn’t do typecasting to an integer, because the result will be 0 in most of the cases and will only be non zero if the angle is exactly pi/2 or 3*pi/2.

I would rather set a threshold. Like this:

double a = Math.sin(Math.toRadians(angle));
if(a < 0.0001 && a > -0.00001)
    a = 0;

In which case would typecasting to integer be better?

Well, I would convert to degrees if you want to display it.

In NO case would typecasting to an integer be better.

You could round off the result to however many decimal places you desire.

E.g.

double result = (int)(1.0e6*sin(angle))/1.0e6

KEEP IT SIMPLE

System.out.printf("%f\n", Math.sin(Math.toRadians(180.0)));

outputs: 0.000000

If you only want to see the high significant digits, use printf with %f instead of println.