Sqrt (1.0 - pow (1.0,2)) returns -nan

I found an interesting floating point problem. I need to calculate a few square roots in my code, and the expression looks like this:

sqrt(1.0 - pow(pos,2))

where pos goes from -1.0 to 1.0 in the loop. -1.0 works fine for pow, but when pos = 1.0, I get -nan. Performing some tests using gcc 4.4.5 and icc 12.0, output

1.0 - pow(pos,2) = -1.33226763e-15

and

1.0 - pow(1.0,2) = 0

or

poss = 1.0
1.0 - pow(poss,2) = 0

Where it is obvious that the first will give problems, be negative. Does anyone know why pow returns a number less than 0? The full violation code is below:

int main() {
  double n_max = 10;
  double a = -1.0;
  double b = 1.0;
  int divisions = int(5 * n_max);
  assert (!(b == a));

  double interval = b - a;
  double delta_theta = interval / divisions;
  double delta_thetaover2 = delta_theta / 2.0;
  double pos = a;
  //for (int i = 0; i < divisions - 1; i++) {
   for (int i = 0; i < divisions+1; i++) {

    cout<<sqrt(1.0 - pow(pos, 2)) <<setw(20)<<pos<<endl;

     if(isnan(sqrt(1.0 - pow(pos, 2)))){
      cout<<"Danger Will Robinson!"<<endl;
      cout<< sqrt(1.0 - pow(pos,2))<<endl;
      cout<<"pos "<<setprecision(9)<<pos<<endl;
      cout<<"pow(pos,2) "<<setprecision(9)<<pow(pos, 2)<<endl;
      cout<<"delta_theta "<<delta_theta<<endl;
      cout<<"1 - pow "<< 1.0 - pow(pos,2)<<endl;
      double poss = 1.0;
      cout<<"1- poss "<<1.0 - pow(poss,2)<<endl;


  }

  pos += delta_theta;

}

 return 0;
 }
+3
source share
4 answers

, 1 - 1 ^ 2 , sqrt.

, :

double x = 1. - pow(pos, 2.);
result = sqrt(x < 0 ? 0 : x);

result = sqrt(abs(x) < 1e-12 ? 0 : x);
+4

pos , > 1.0. pos , .

+8

setprecision(9) . , , . , , .

+2

, 15 (52 ), . IEEE , , . .

pos 14 . 0 sqrt.

pos

pos = round(a + interval * i / divisions, 14);

,

double round(double r, int digits) 
{
    double multiplier = pow(digits,10);
    return floor(r*multiplier + 0.5)/multiplier;
}
0

Source: https://habr.com/ru/post/1780500/


All Articles