1

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?

Murphy Ng
  • 177
  • 7

2 Answers2

5

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 *)
ilian
  • 25,474
  • 4
  • 117
  • 186
  • 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 08 '20 at 00:00
  • 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? – Murphy Ng Jun 08 '20 at 00:04
  • I did some experiment according to you answer and got a strange result. Could you see my updated question, please? – Murphy Ng Jun 08 '20 at 00:52
  • 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. – ilian Jun 08 '20 at 05:57
  • 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 08 '20 at 06:02
  • For example, Block[{Internal\$EqualTolerance = 0}, 1`2 == 101/100]` is True. If you want it to be false, the tolerance should be set lower. By "the same is true" I meant that your exactNum is also an approximation of Pi. – ilian Jun 08 '20 at 06:20
  • In Block[{Internal`$EqualTolerance = 0}, 1`2 == 101/100],I wonder how can EqualTolerance be set lower? it's already zero. The reason 1`2 == 101/100 is because the mechanism of Mathematica comparing between an exact number 101/100 and an inexact number 1`2 : as long as 101/100 lies in the interval represented by the inexact number 1`2, they are considered equal. I know this theory isn't documented anywhere, I just figure it out myself. Maybe I'm wrong about this in the first place? – Murphy Ng Jun 08 '20 at 06:25
  • The point of the example was that it is definitely not a "strictly precise" comparison. In any case, if you want a bound for the difference approPi - exactNum, that should be 10^-Accuracy[approPi]. – ilian Jun 08 '20 at 14:56
  • I agree it's note a "strictly precise" comparison. But Mathematica must have a very clear self-defined rule when comparing an exact number and an inexact number, right? My guess is that this rule is: When comparing between an exact number such as 101/100 and an inexact number such as 12 , as long as 101/100 lies in the interval represented by the inexact number 12, they are considered equal. It's my guess according to many experiment(some of them don't hold) Have you considered what's this hidden rule looks like? – Murphy Ng Jun 09 '20 at 00:37
3

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]
Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • These aren't documented anywhere, right? I find it so hard to figure out the whole mechanism of number precision. – Murphy Ng Jun 07 '20 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 08 '20 at 00:06
  • I used the NumericalMath$NumberBits[num]which return the same number asSetPrecision[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 08 '20 at 06:50