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=345500`3
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.1415926535897932384626433832795028842`11. 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?