C++ conversion from decimal degrees to DMS

83 Views Asked by At

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 !

0

There are 0 best solutions below