I am trying to convert a floating-point double-precision value x
to decimal with 12 (correctly rounded) significant digits. I am assuming that x
is between 10^110 and 10^111 such that its decimal representation will be of the form x.xxxxxxxxxxxE110
. And, just for fun, I am trying to use floating-point arithmetic only.
I arrived to the pseudo-code below, where all operations are double-precision operations, The notation 1e98
is for the double nearest to the mathematical 10^98, and 1e98_2
is the double nearest to the result of the mathematical subtraction 10^98-1e98
. The notation fmadd(X * Y + Z)
is for the fused multiply-add operation with operands X
,Y
, Z
.
y = x * 2^-1074; // exact
q = y / 1e98; // q is denormal and the significand of q interpreted
// as an integer is our candidate for the 12 decimal
// digits of x
r = fmadd(q * 1e98 - y); // close to 1e98 * (error made during the division)
// If 1e98_2 >= 0, we divided by a number that was smaller than we wished
// The correct answer may be q or q+1.
if (r and 1e98_2 have opposite signs)
{
return the significand of q;
}
s = copysign(2^-1074, r);
r1 = abs(r);
r2 = abs(1e98_2);
h = 1e98 * 0.5 * 2^-1074;
Set rounding mode to downwards
r3 = fmadd(r2 * q + r1);
if (r3 < h)
{
return the significand of q;
}
else
{
return significand of (q + s)
}
I apologize for the confusion that pervades the above pseudo-code, but it is not very clear for me yet, hence the following questions:
Does the first fmadd work as intended (to compute 1e98 * (error made during the division))?
The signs. I cannot convince myself that they are right. But I cannot convince myself that they are wrong either.
Any idea, perhaps arguments, about the frequency with which this algorithm might produce the wrong result?
If it works at all, is there any chance that the algorithm will continue to work if “q = y / 1e98” is changed to “q = y * 1e-98” (leaving all other instructions the same)?
I have not tested this algorithm. I do not have any computer with a fmadd instruction, although I hope to find one so that I can execute the above.