I have the following code to convert decimal degrees to/from degrees,minutes,seconds.
#include <cmath>
#include <iostream>
void toDMS(double decimalDegrees, int& degrees, unsigned int& minutes, double& seconds)
{
degrees = static_cast<int>(decimalDegrees);
double remainingMinutes = fabs(decimalDegrees - degrees) * 60.0;
minutes = static_cast<unsigned int>(remainingMinutes);
seconds = (remainingMinutes - minutes) * 60.0;
}
double toDecimalDegrees(int degrees, unsigned int minutes, double seconds)
{
if (degrees >= 0.0)
return fabs(degrees) + (minutes / 60.0) + (seconds / 3600.0);
else
return -(fabs(degrees) + (minutes / 60.0) + (seconds / 3600.0));
}
But when I run the following test :
int main(int argc, char** argv)
{
double decimalDegrees = 45.666666666666664;
int degrees; unsigned int minutes; double seconds;
toDMS(decimalDegrees, degrees, minutes, seconds);
std::cout << "DMS = " << degrees << ", " << minutes << ", " << seconds << std::endl;
}
I get : 45, 39, 60
Instead of : 45, 40, 0
This is due to a precision issue, remainingMinutes contains 39.9999999... instead of 40.0.
I can get around with something like :
double remainingMinutes = fabs(decimalDegrees - degrees) * 60.0;
double ceil = std::ceil(remainingMinutes);
if (ceil - remainingMinutes <= 1.0e-10)
remainingMinutes = ceil;
But I don't like this, because I must use an arbitrary precision and the bug could happen with other numerical values.
Anyone has a better alternative ? Many thanks !