How to get exact Rationalize of a decimal number?

You can use SetPrecision to find a more precise result.

r0 = 0.97646105481464028;
r1 = Rationalize[r0]

r2 = SetPrecision[r0, Infinity]

8795179285210031/9007199254740992

r2 - r0

0.

If you increase the Precision of your input, you can get a rational number that is closer to 0.97646105481464028.

Precision@r0

MachinePrecision

r0 = 0.97646105481464028`100;
Precision@r0

100.

r3 = SetPrecision[r0, Infinity]

17086121198925650302678220692982191831883180533886836969508025507253230621682061409501393058711047971/ 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592


Comparing with your Maple result:

maple = 24411526370366007/25000000000000000;

N[maple, 17]
N[r2, 17]
N[r3, 17]

0.97646105481464028
0.97646105481464029
0.97646105481464028


When you simply input 0.97646105481464028, you do not get this number internally:

0.97646105481464028 // FullForm
0.9764610548146403`

Hence you can't expect any internal function to return exactly 97646105481464028/100000000000000000 from the above numeric input.

In order to preserve exact decimal representation of the original number, you need to specify explicit Precision or Accuracy (which do the same in this particular case):

RealDigits[0.97646105481464028`17]
RealDigits[0.97646105481464028``17]
{{9, 7, 6, 4, 6, 1, 0, 5, 4, 8, 1, 4, 6, 4, 0, 2, 8}, 0}

{{9, 7, 6, 4, 6, 1, 0, 5, 4, 8, 1, 4, 6, 4, 0, 2, 8}, 0}
FromDigits[%]
% - 97646105481464028/100000000000000000
24411526370366007/25000000000000000

0

Note that RealDigits drops the sign, hence in the general case you have to multiply the output of FromDigits by Sign:

Sign[#]*FromDigits[RealDigits[#]] &@-0.97646105481464028`17
-(24411526370366007/25000000000000000)

Question: How to get exact Rationalize for the above from Mathematica?

It depends on what do you mean under the "exact" rational representation of an inexact number. One approach via RealDigits I have given above. Rationalize and SetPrecision implement other approaches:

Rationalize[x,0] gives a rational that is equivalent to x up to the precision of x

SetPrecision[x,∞] gets a rational directly from the bitwise representation of x


In the comment Hurkyl gives a concise explanation why Rationalize doesn't give an "exact" representation by default:

Incidentally, the main application of Rationalize is when you've numerically computed a rational number (or what you hope to be a rational number), and you want to obtain the true rational value from its numerical approximation. Exactly representing the specific floating-point approximation is the wrong answer to this problem.


I've found, empirically, that I can ensure Rationalize[ ] provides an exact rational conversion of whatever decimal I enter (call it "num") if I evaluate Rationalize[num`z, 0] where:

$z \geq 2*\text{Length@RealDigits[num][[1]]} + 1$

E.g.,

Length@RealDigits[0.97646105481464028][[1]]
==>16

so:

Rationalize[0.97646105481464028`33, 0]
==>24411526370366007/25000000000000000

24411526370366007/25000000000000000==97646105481464028/100000000000000000
==>True

but

Rationalize[0.39984759300000068`32, 0]
==>5594893179322259/5729765822953714

5594893179322259/5729765822953714==97646105481464028/100000000000000000
==>False

I'd like to understand why that's the cutoff*, so I'll be posting my own question on that soon. [*That's the general cutoff; there are some decimals that are exactly converted with a lower value of z, but I've not found any that require a higher value for z.]

Alternately, you can also achieve an exact rational conversion using Round[num`y, 10^-y], where (again, empricially), I've found that:

$y \geq \text{Length@RealDigits[num][[1]]} + 1$

Thus:

Round[0.97646105481464028`17, 10^-17]
==>24411526370366007/25000000000000000

but

Round[0.39984759300000068`16, 10^-16]
==>5594893179322259/5729765822953714

Finally, one way to understand why SetPrecision[num`z, Infinity] won't generally give an exact rational conversion of the decimal you enter is that SetPrecision[ ] is restricted to converting "num" to that subset of rational base-10 numbers that can be represented in binary with a finite number of digits; it then pads that binary with an infinite number of zeros. And, while there are exceptions (e.g., 0.5), decimals typically can't be exactly represented with a finite binary.

Thus:

RealDigits[SetPrecision[0.97646105481464028`33, Infinity], 2, 300]

==>{1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 
0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 
1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 
1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0}

and

Take[RealDigits[SetPrecision[0.97646105481464028`33, Infinity], 2, 
   10^9][[1]], -100]

{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0}

But:

RealDigits[Rationalize[0.97646105481464028`33, 0], 2, 300]

==>{1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 
0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 
1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 
1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 
1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 
0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 
1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 
1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 
1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 
1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 
0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1,
  1}

and

Take[RealDigits[Rationalize[0.97646105481464028`33, 0], 2, 
   10^9][[1]], -100]

{1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 
0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 
1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 
0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 
1, 0, 1, 1, 1, 0, 0, 0}

You might also want to take a look at the answer by george2079 here: Enter exact rational numbers easily with decimal notation

Note also that the part of the documentation you quoted with p,q,c applies only to the single-argument Rationalize[x] forms, as noted by sn6uv here: Rationalize error. For the dual-argument forms, Rationalize[x, dx] (excepting where dx = 0, which is what I was using above), Daniel Lichtblau, at that same link, says: "I'd say the documentation could be worded better for the 2-argument case of Rationalize. There is an interplay between denominator of result, epsilon, and size of residual. If you take dx as replacing the default epsilon then I think the correct claim might be to the effect: ratPi = Rationalize[N[Pi], eps]; Abs[N[Pi] - ratPi] < N[eps]/Denominator[ratPi]^2."