double trouble

Don Clugston dac at nospam.com.au
Wed Mar 1 05:47:05 PST 2006


John C wrote:
> I'm writing routines for numeric formatting and this involves round-tripping 
> of floating-point numbers. I'm storing the integral and fractional parts in 
> a string buffer, and in a separate variable storing the decimal point 
> position, and these are converted back into a double when needed. 
> Unfortunately the algorithm I'm using is too lossy and as a result a number 
> like 2.78 (stored in the buffer as "278", with the decimal pos being 1) 
> becomes 2.7799999999998.

The trick to maximal efficiency in these conversions is to make sure 
that you only do ONE division (because that's the point at which the 
rounding error occurs). Don't divide by 10 every time, and definitely 
don't use pow. Instead, keep track of a denominator, and every time 
you'd do a v/=10, do denominator*=10 instead. Then, right at the end, 
divide v by denominator.
The reason this works is that integers can be exactly represented in 
reals, so the multiplies aren't introducing any error. But every time 
you divide by something that isn't a multiple of 2, a tiny roundoff 
error creeps in.
You'll also reduce the error if you use
real v=0.0;
instead of double. Even if you ultimately want a double.

> 
> I believe the problem is with my scaling code. Any ideas to increase the 
> accuracy?
> 
>   // v is a numeric representation of the digits, eg 278.
>   // exponent is either the exponent for scientific numbers, or the number 
> of fractional digits, eg 2.
>   double p10 = 10.0;
>   int n = exponent;
>   if (n < 0)
>     n = -n;
>   while (n) {
>     if (n & 1) {
>       if (exponent < 0)
>         v /= p10;
>       else
>         v *= p10;
>     }
>     n >>= 1;
>     p10 *= p10;
>   }
> 
> 



More information about the Digitalmars-d mailing list