Search code examples
c++solarisprecisiondouble-precisionscientific-notation

double to scientific notation conversion - precision error


I'm writing a piece of code to convert double values to scientific notations upto a precision of 15 in C++. I know I can use standard libraries like sprintf with %e option to do this. But I would need to come out with my own solution. I'm trying something like this.

double norm = 68600000;
if (norm)
{
    while (norm >= 10.0)
    {
      norm /= 10.0;
      exp++;
    }
    while (norm < 1.0)
    {
      norm *= 10.0;
      exp--;
    }
}

The result I get is

norm = 6.8599999999999994316;
exp = 7

The reason for loosing this precision I clarified from this question

Now I try to round the value to the precision of 15, which would result in

6.859 999 999 999 999

(its evident that since the 16th decimal point is less than 5 we get this result)

Expected answer: norm = 6.860 000 000 000 000, exp = 7

My question is, is there any better way for double to scientific notation conversion to the precision of 15(without using the standard libs), so that I would get exactly 6.86 when I round. If you have noticed the problem here is not with the rounding mechanism, but with the double to scientific notation conversion due to the precision loss related to machine epsilon


Solution

  • You could declare norm as a long double for some more precision. long double wiki Although there are some compiler specific issues to be aware of. Some compilers make long double synonymous with double.

    Another way to go about solving this precision problem is to work with numbers in the form of strings and implement custom arithmetic operations for strings that would not be subject to machine epsilon. For example:

    int getEXP(string norm){ return norm.length() - 1; };
    
    string norm = "68600000";
    int exp = getEXP(norm); // returns 7
    

    The next step would be to implement functions to insert a decimal character into the appropriate place in the norm string, and add whatever level of precision you'd like. No machine epsilon to worry about.