1
$\begingroup$

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?

Strange result


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?

$\endgroup$

2 Answers 2

5
$\begingroup$

This is another way to get the exact number stored internally, including any guard bits:

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 *)
$\endgroup$
9
  • $\begingroup$ 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. $\endgroup$
    – Murphy Ng
    Commented Jun 8, 2020 at 0:00
  • $\begingroup$ So Wolfram indeed 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. Right? $\endgroup$
    – Murphy Ng
    Commented Jun 8, 2020 at 0:04
  • $\begingroup$ I did some experiment according to you answer and got a strange result. Could you see my updated question, please? $\endgroup$
    – Murphy Ng
    Commented Jun 8, 2020 at 0:52
  • $\begingroup$ I am not sure I understand the reasoning. approPi is an approximation of Pi with some precision, so it is going to be within some interval around Pi. The same is true for the rational exactNum, except it will be a tighter interval because of the extra bits. How did you derive your interval estimate for approPi based on exactNum? Besides, the inequality comparison is also inexact, it is done only to some precision. $\endgroup$
    – ilian
    Commented Jun 8, 2020 at 5:57
  • $\begingroup$ 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? $\endgroup$
    – Murphy Ng
    Commented Jun 8, 2020 at 6:02
3
$\begingroup$

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]
$\endgroup$
3
  • $\begingroup$ These aren't documented anywhere, right? I find it so hard to figure out the whole mechanism of number precision. $\endgroup$
    – Murphy Ng
    Commented Jun 7, 2020 at 23:54
  • $\begingroup$ @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 $\endgroup$
    – Michael E2
    Commented Jun 8, 2020 at 0:06
  • $\begingroup$ 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? $\endgroup$
    – Murphy Ng
    Commented Jun 8, 2020 at 6:50

Not the answer you're looking for? Browse other questions tagged or ask your own question.