I generally prefer to do all my intermediate calculations with exact numbers, and then round my result at the end. Thus I will typically convert each arbitrary-precision number to its exact equivalent; e.g., 1.7 becomes 17/10. However, the only method I've found that ensures numerically exact conversion is the manual one: delete the decimal point, and then divide by 10^z, where z is the number of digits to the right of the decimal.
For instance, consider a = 399847593.00000068
. If I use the above method, I get a fraction that is exactly equal to a
. Is there a command that achieves this?
Edit added for clarity: I'm not looking for exact rational representations of the computer's internal binary representation of base-10 floating point numbers; I understand the latter typically can't be exactly equal to the floating point. Rather, I'm looking for exact rational representation of the floating point numbers themselves (which the software can do, if I enter them manually), which will then effectively be carried through the entire calculation. At the end of the calculation, final cancellations, and numerical conversion to a floating point, if desired, can then be done.
I tried SetPrecision[a,Infinity]
and SetAccuracy[a, Infinity]
, but both give fractions that are not exactly equal to a
(see screenshot below). Why is this? [Edit: I've removed my speculations here, since Szabloc's answer explains the behavior of these commands.]
From the name, Rationalize
might seem to be a good candidate, but Rationalize[a, 0]
likewise doesn't give a numerically exact conversion, as expected from the documentation: "Rationalize[x,0]
gives a rational number equivalent to x up to the precision of x." Finally, multiplying by 10^z (see first paragraph), applying Floor
, and then dividing by 10^z likewise doesn't achieve the desired result:
{a = 399847593.00000068, Precision[a] // N}
mExact = 39984759300000068/10^8; (*manual method*)
mNum25 = NumberForm[N[mExact, 25],
ExponentFunction -> (If[-Infinity < # < Infinity, Null, #] &)];
{mExact, Precision[mExact], mNum25}
pExact = SetPrecision[a, Infinity]; (*SetPrecision method*)
pNum25 = NumberForm[N[pExact, 25],
ExponentFunction -> (If[-Infinity < # < Infinity, Null, #] &)];
{pExact, Precision[pExact], pNum25}
aExact = SetAccuracy[a, Infinity]; (*SetAccuracy method*)
aNum25 = NumberForm[N[aExact, 25],
ExponentFunction -> (If[-Infinity < # < Infinity, Null, #] &)];
{aExact, Precision[aExact], aNum25}
rExact = Rationalize[a, 0]; (*Rationalize method*)
rNum25 = NumberForm[N[rExact, 25],
ExponentFunction -> (If[-Infinity < # < Infinity, Null, #] &)];
{rExact, Precision[rExact], rNum25}
fExact = Floor[a*10^8]/10^8; (*Floor method*)
fNum25 = NumberForm[N[fExact, 25],
ExponentFunction -> (If[-Infinity < # < Infinity, Null, #] &)];
{fExact, Precision[fExact], fNum25}