# Does SetPrecision[x, Infinity] expose the internal exact number in the approximated number?

## What I already know (maybe) :

### My theory about Mathematica's way of implementing approximated number

An number approX with arbitrary precision prec represents not a point on number axis but an interval Interval[{approX - approX*10^-prec, approX + approX*10^-prec}]. Things like an approximated number doesn't exist in computer system anyhow. Everything in computer is an exact an precise binary number. So, Approximated number in Mathematica is implemented using two exact number: a exact number as the interval's middle point, and a precision value representing the span of interval. The following code shows this theory:

approX=3455003
exactX=SetPrecision[approX,Infinity](* Output 345500. Expose the underlying exact number inside approX *)
intervalX =Interval[{exactX-exactX*10^-3,exactX+exactX*10^-3}];
N[intervalX,10](* convert to real number for demonstration convinience, {345154.49992,345845.50007} *)
Block[{Internal$EqualTolerance=0},345155==approX](*Output true, since 345155 lies in {345154.49992,345845.50007}*) Block[{Internal$EqualTolerance=0},345154==approX](*Output false, since 345154 doesn't lies in {345154.49992,345845.50007}*)
Block[{Internal$EqualTolerance=0},345845==approX](*Output true, since 345845 lies in {345154.49992,345845.50007}*) Block[{Internal$EqualTolerance=0},345846==approX](*Output false, since 345846 doesn't lies in {345154.49992,345845.50007}*)


So, I thought Wolfram use two field to store a arbitrary precision number: one field is an binary value x represents the middle point of the interval, another field is a value represent the precision. These two value together are used to serve the purpose of error tracking during all kinds of calculation. Am I correct?

## What I don't understand :

If the exact number representing approPi internally can be get via SetPrecision[x, Infinity], why SetPrecision[approPi, Infinity] is very different with approPi // InputForm in the following code? ## Updated, after seeing @ilian's NumericalMath-NumberBits[approPi] trick

Thanks for the answer by @ilian. I almost get everything straight, except for what happened in the last line of code:

Clear["*"]
approPi=N[Pi,5](* Output 3.141592653589793238462643383279502884211. Simply as a convenient way to get a decimal number  *)
{sign,goodbits,badbits,expon}=NumericalMath$NumberBits[approPi]; exactNum =sign*FromDigits[{Join[goodbits,badbits],expon},2](* Get the underlying exact number of this approximated number approPi *) interval = Interval[{exactNum-exactNum*10^-5, exactNum+exactNum*10^-5}] Block[{Internal$EqualTolerance=0},Min[interval]==approPi] (* Output true. This is the lower bound of approPi's value interval *)
Block[{Internal$EqualTolerance=0},Min[interval]-10^-999<approPi](* Output true. After subtracting by a very small number, it's beyond the lower bound *) Block[{Internal$EqualTolerance=0},Max[interval]==approPi](* Output true. This should be the upper bound of approPi's value interval *)
Block[{Internal$EqualTolerance=0},Max[interval]+10^-999>approPi](* Output false. I expected it to be True. *) Block[{Internal$EqualTolerance=0},Max[interval]+10^-99>approPi](* Still output false.  It seems that Max[interval] isn't the upper bound of what approPi represents *)


Above shows that exactNum+exactNum*10^-5 isn't the actual upper bound. However, the exactNum-exactNum*10^-5 indeed proves to be the lower bound. Very Strange result, why?

num = N[Pi, 5];
{sign, goodbits, badbits, expon} = NumericalMath$NumberBits[num]; sign * FromDigits[{Join[goodbits, badbits], expon}, 2] (* 57952155664616982739/18446744073709551616 *)  which agrees with Michael E2's suggestion SetPrecision[SetPrecision[num, Precision[num] + 32], Infinity] (* 57952155664616982739/18446744073709551616 *)  • Things like NumericalMath$NumberBits[num] aren't documented anywhere, right? I find it so hard to figure out the whole mechanism of number precision. And the official documentation about SetPrecision mislead me to believe it can expose the internally stored exact number inside a approximated number. – Murphy Ng Jun 8 at 0:00
• As for "the inequality comparison is also inexact, it is done only to some precision", I deliberately set the Internal$EqualTolerance=0 to achieve strictly precise equality. As for "The same is true for the rational exactNum ", exactNum is a exact number, representing a point on number axis. Only approximated number represents an interval on number axis. Am I correct? – Murphy Ng Jun 8 at 6:02 SetPrecision[x, Infinity] is equivalent to Round[x, 2^Floor@Log2[10^-Accuracy[x]]]. That is, you get the bits up to the Accuracy[] of the number. To get the extra guard bits, increase the accuracy of x (not entirely sure what a necessary increment is — I have not needed more than an extra 29 digits in experiments): SetPrecision[SetPrecision[x, Precision[x] + 32], Infinity]  • These aren't documented anywhere, right? I find it so hard to figure out the whole mechanism of number precision. – Murphy Ng Jun 7 at 23:54 • @MurphyNg It was a typo. I don't know of any documentation. I figured things out by experimentation. There might be something in the Wolfram Library at wolfram.com – Michael E2 Jun 8 at 0:06 • I used the NumericalMath$NumberBits[num] which return the same number as SetPrecision[SetPrecision[x, Precision[x] + 32], Infinity]. But after some experiment, I found things are more complicated than I thought. Could you checkout my updated question, please? – Murphy Ng Jun 8 at 6:50