#include <stdio.h>

#include <math.h>

#include <float.h> // comment that our

int main () {

float f = 1.0;

printf("'acos(%f)' is %f\n",f,acos(f));

return 0;

}

I assume that the problem lies elsewhere...

Solved

Posted on 2006-05-29

I had a situation where the result of an acos() was NAN. The argument seemed to be 1.00000 but it did not compare to (== 1.0) so it must have been off by a bit and was causing acos to return and NAN result. So, to check for this I was going to use _isnan(), so I included float.h in my file. All of a sudden, acos no longer returns NAN with the same argument. It now returns zero like it should with an argument of 1.000000000. How did just including float.h cause this to correct itself?

17 Comments

#include <stdio.h>

#include <math.h>

#include <float.h> // comment that our

int main () {

float f = 1.0;

printf("'acos(%f)' is %f\n",f,acos(f));

return 0;

}

I assume that the problem lies elsewhere...

_isnan(1.0);

And I consistently cause (without it) or fix (with it) the problem. Completely reproducable.

You should not test floating point values for accuracy like that - they'll never match. Better use

#include <limits>

bool is_equal(double d1, double d2) {

return fabs(d1 - d2) < std::numeric_limits<double

}

Could specify what compiler you are using and the code that is leading to this?

That's already the prerequisite for 'acos()' also...

The function simply computes the great circle distance between two lat/lon points in miles. If I comment out the lines that test for _isnan() the acos() function returns NAN when the input lat/lon points are the same (i.e. dist should be zero)... with the line uncommented, the acos() function returns zero as it should.

int MilesBetween( double dALat, double dALon, double dBLat, double dBLon )

{

double dCentAng;

double dFactor = M_PI / 180.0;

// Degrees to radians

dALat *= dFactor;

dALon *= dFactor;

dBLat *= dFactor;

dBLon *= dFactor;

// Find GC distance

dCentAng = acos((sin(dALat) * sin(dBLat)) + (cos(dALat) * cos(dBLat) * cos(fabs(dALon - dBLon))));

if( _isnan(dCentAng) )

return -1;

// Radians to degrees

dCentAng = (dCentAng * 180.0) / M_PI;

return (int) ((dCentAng * 60.0) + 0.5);

}

Regards, Alex

cA=cos(dAlat);

cB=cos(dBlat);

sA=sin(dAlat);

sB=sin(dBlat);

cD=cB*cos(dAlon-dBlon);

c2=cB*sin(dAlon-dBlon);

c1=cA*sB-sA*cD;

dCentAng = atan2(sqrt(c2*c2+c1*c1),sA

Try to compile with different /fp: flags. See:

http://msdn2.microsoft.com

http://msdn2.microsoft.com

http://msdn.microsoft.com/

As explained above acos is *not defined* for arguments < -1 and > +1.

If your calculations are valid but could give results that were very near to 1 or -1, you need to make sure that the absolute value of the argument never exceeds 1. You might use a rounding function like that:

double roundCos(double d)

{

return (d < -1.)? -1 : (d > 1.) ? 1 : d;

}

However, first you should check whether acos(-1.) and acos(1.) return valid results.

Regards, Alex

By clicking you are agreeing to Experts Exchange's Terms of Use.

Title | # Comments | Views | Activity |
---|---|---|---|

Hide or Show Images using checkbox array in mysql database | 11 | 214 | |

css help | 3 | 77 | |

Better understanding on C++ Class serialization and formats | 9 | 31 | |

C++ error cannot convert from std::string to const char * | 6 | 30 |

Join the community of 500,000 technology professionals and ask your questions.

Connect with top rated Experts

**14** Experts available now in Live!