简体   繁体   中英

Weird floating point error?

I've been trying to generate a pattern of circles using a for loop. However, when it runs everything looks fine except for the 9th ring of circles which is ever so slightly. Having looked at a print out of numbers for that circle everything looks fine, so I can't work out what is going wrong. However, when I add one to the angle value of that ring. ie j (the commented out code) it pretty much corrects.

Any idea why this might happen. having looked at all the numbers I can only think it is some math error that I haven't factored in or am I missing something obvious.

Thanks!

OCD触发警告

          ellipse(325,325,15,15);      
          float div = 1;
          for (int i = i; i < 25; i++)
          {
            div = i*6
            float segment = 360/div;
            float radius = (i*20);
            for (int j = 0; j < 360; j+=segment)
            {
              //if (i==8)
              //{
                //println("before " + j);
                //j+=1;
                //println("after " + j);
              //}
              float x = 325 + (radius*cos(radians(j)));
              float y = 325 + (radius*sin(radians(j)));
              ellipse(x, y, 15, 15);
            }
          }

You get the segment as a float , but then you use an int to calculate the degrees.

for (int j=0; j < 360; j+=segment)

and

float x = 325 + (radius*cos(radians(j)));

This is what is causing the rounding errors.

And if you make i to get a value bigger than 60 the program will never end.

Ok, three things, in order of importance. Two of these have already been mentioned.

1) Clean out the int s. Variable i can be an int , but none of the others (especially j since it is an angle, not a counter or index), and you want to make sure that all math operations treat numbers as double s. Go so far as to designate your constants as double s (eg use 1d instead of 1 ).

2) Avoid cumulative errors. In your inner for loop, you repeatedly add to j . Bad. Instead, compute your angle directly based on which circle you're computing.

3) Use double , not float . You'll get better precision.

I'd do it like this...

ellipse(325,325,15,15);      
for (int i = i; i < 25; i++)
{
  double div = i*6d;
  double radius = (i*20d);
  for (int j = 0; j < div; j++)
  {
    double theta = j * 360d / div;
    double x = 325d + (radius*cos(radians(theta)));
    double y = 325d + (radius*sin(radians(theta)));
    ellipse(x, y, 15, 15);
  }
}

Use double instead of float to minimise representation error.

Change the for loop to reduce error.

for (int k = 0; k < div; k++) {
    int j = k * 360 / div; 

This will give you different values for j which are likely to be more correct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM