0

So I'm taking an online Java course and the task is as follows:

In this program we are going to practice using the Math class by computing some important values on the unit circle. Starting at 0 and going up by PI/4 radians (or 45 degrees), print out information of the format below.

    Radians: (cos, sin)
    0.0: 1.0, 0.0
    0.79: 0.7, 0.71
    1.57: 0.0, 1.0
    2.36: -0.71, 0.7
    3.14: -1.0, 0.0
    3.93: -0.7, -0.71
    4.71: 0.0, -1.0
    5.5: 0.71, -0.71

Hint: You’ll need to use the Math.sin, Math.cos methods and the Math.PI constant! You’ll also need to loop from 0 to 2*PI

Here is what I came up with:

    public class UnitCircle extends ConsoleProgram
    {
        public void run()
        {
            System.out.println("Radians: (cos, sin)");
            for(double count = 0; count <= Math.PI * 2; count += Math.PI / 4)
            {
                System.out.println(count + ": " + Math.cos(count) + ", " + Math.sin(count));
            }
        }
    }

However when I run it, this is what I get:

    Radians: (cos, sin)
    0.0: 1.0, 0.0
    0.7853981633974483: 0.7071067811865476, 0.7071067811865475
    1.5707963267948966: 6.123233995736766E-17, 1.0
    2.356194490192345: -0.7071067811865475, 0.7071067811865476
    3.141592653589793: -1.0, 1.2246467991473532E-16
    3.9269908169872414: -0.7071067811865477, -0.7071067811865475
    4.71238898038469: -1.8369701987210297E-16, -1.0
    5.497787143782138: 0.7071067811865474, -0.7071067811865477
    6.283185307179586: 1.0, -2.4492935982947064E-16

What's up with that? Could it be that I need to limit the calculations to round to 2 decimal places? What else am I doing wrong? Any help would be greatly appreciated.

Gidgit
  • 1
  • 1
  • 2
  • "Could it be that I need to limit the calculations to round to 2 decimal places?" Yes. I don't know why the example results show different amounts of significant figures for `sin(PI/4)` and `cos(PI/4)` as they should be almost identical, as can be seen in your `0.7071067811865476, 0.7071067811865475` output - ignore that sample and stick to two decimal places, I would advise. – Ken Y-N Jan 05 '17 at 02:56

1 Answers1

0

The simplest solution is to format of the output using a simple print statement: System.out.format("%.2f: %.2f, %.2f"); This is simple and will let you move onward, but there is always more to learn both about formatting numbers and about the way machines represent numbers!

The formatting problem is that the implicit conversion process used in the System.out.println statements doesn't meet the goals for rounding and spacing. We want to control that formatting process to produce a cleaner looking output. Note that formatting the string output through printf-style truncation is a slightly different concept than rounding. Rounding occurs with an explicit rounding statement like Math.round or a class like NumericFormat or DecimalFormat. The comments already point to a good reference on SO to formatting numbers. The Oracle documentation online has more detailed information: https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html

The more interesting problem has to do with how machines (and the JVM) store and compute numeric values. Look at the method prototypes; both Math.cos and Math.sin methods return a double. This is one of Java's primitive types used to represent numeric values. Machines represent and perform math operations on numeric values isn't quite perfect.

Java's double is based on a standard (IEEE754) that specifies a specific use of 64 bits to represent the number. Doubles an floats are used in machines to represent real numbers (think continuous values, not only the integers). It is simple to observe that a 64-bit value cannot perfectly represent all real numbers; there are an infinite number of real values but only 2^64 unique doubles. There is a standard for floats that uses only 32-bits to represent all the real numbers. This means there can be differences between the actual value and the represented values. It is possible to see differences between values that are in fact identical when computed in different ways (e.g. Math.sin(Math.PI/4) == Math.cos(Math.PI/4)). The difference between the true and represented values are so small to not make an impact in the application.

Ben
  • 1,234
  • 2
  • 8
  • 5