1

I am taking an online course and I am supposed to create a program like this:

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

Hints:

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

My program looks like this:

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

But when I run it this is what I get:

Radians: (cos, sin)
0.0: 1.0, 0.0
0.79: 0.7, 0.71
1.58: -0.01, 1.0
2.37: -0.72, 0.7
3.16: -1.0, -0.02
3.95: -0.69, -0.72
4.74: 0.03, -1.0
5.53: 0.73, -0.68

I don't know how to fix this. I suspect that I have a problem with rounding numbers but I have no idea how to fix that.

Plapatine
  • 11
  • 3

1 Answers1

1

There are several issues, none of them major.

i = Math.round(i * 100) / 100.0;

You are modifying the loop index variable inside the loop, which is bad practice.

Second, you are rounding the index variable, which causes the mismatch between your actual and expected results. For example, at the beginning of the second iteration, the value of i differs from π/4 by an infinitesimal amount (one part in about 1014, but when you round i, you've truncated it to 0.79, which is off quite a bit. Using that going forwards you add more error each time.

To solve the problem, do not round i (don't modify it in any way), and perform all calculations with full precision (i.e. do not round any intermediate numeric values).

Conceptually, you want to completely separate the calculation from the display. Always do the calculation with the largest available precision and apply rounding or truncation only when rendering the results for printing.

Note that you may still get some counter-intuitive results in some edge cases. If you're going to work with floating point numbers you MUST read What Every Computer Scientist Should Know About Floating-Point Arithmetic and Is Floating Point Broken?

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
  • applyIng rounding only to the answers just before printing may not work because the internal representation is still binary, not decimal. – Mad Physicist May 13 '18 at 04:26
  • Don't waste your time reading *What every computer scientist ...* As the title indicates it is addressed at *every computer scientist*, if the author had meant to address it to every computer programmer he (I think it's a he) would have called it *What every computer programmer ...*. It's a resource for those implementing floating-point arithmetics, not for regular users of f-p arithmetic, for which there are far better tutorials, including *Is Floating Point Broken*. – High Performance Mark May 13 '18 at 10:47