Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Strange Behavior with Sin and ToRadians

Tags:

java

I have been given the task of using java to produce a Sin table, however I seem to get some very weird results for some values of the input. I am using the below

System.out.println("| sin(" + currentPoint + ") = " + Math.sin(Math.toRadians(currentPoint)));

Where (int) currentPoint is a value in degrees (eg 90)

These are results I find weird

| sin(360) = -2.4492935982947064E-16
| sin(180) = 1.2246467991473532E-16
| sin(150) = 0.49999999999999994
| sin(120) = 0.8660254037844387

Expecting

sin(360) = 0
sin(180) = 0
sin(150) = 0.5
sin(120) = 0.866025404

Am I missing something?

like image 545
Pez Cuckow Avatar asked Oct 18 '10 17:10

Pez Cuckow


2 Answers

You're dealing with floating point numbers, looking for exact answers isn't going to work for all values. Take a look at What Every Computer Scientist Should Know About Floating-Point Arithmetic. You want your tests to be equivalent to your expectations within some delta. Note that the answers you're getting are pretty close. It's expressing values in bits that's biting you.

From the link:

Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation. Although there are infinitely many integers, in most programs the result of integer computations can be stored in 32 bits. In contrast, given any fixed number of bits, most calculations with real numbers will produce quantities that cannot be exactly represented using that many bits. Therefore the result of a floating-point calculation must often be rounded in order to fit back into its finite representation. This rounding error is the characteristic feature of floating-point computation.

like image 135
Paul Rubel Avatar answered Sep 21 '22 12:09

Paul Rubel


If your code was System.out.println("| sin(" + currentPoint + ") = " + Math.sin(currentPoint)); you would expect this:

sin(360) = 0.958915723 
sin(180) = -0.801152636 
sin(150) = -0.71487643 
sin(120) = 0.580611184 

In other words, the sine of 360 radians is 0.9589, but the sine of 360 degrees is 0.

EDIT:
The reason you're seeing unexpected results is just due to lack of precision in the calculations. If you just format the results so they have fewer decimal places, the rounding will take care of it. Do something like this:

System.out.printf("| sin(%d) = %.7f\n", currentPoint, Math.sin(Math.toRadians(currentPoint)));

Then you will get results closer to what you expect.

like image 37
Gabe Avatar answered Sep 18 '22 12:09

Gabe