Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Put - Get cycle in Mathematica always deterministic?

In Mathematica as in other systems of computer math the numbers are internally stored in binary form. However when exporting them with such functions as Put and PutAppend they are converted into approximate decimals. When you import them back with such functions as Get they are restored from this approximate decimal representation to binary form.

The question is whether the recovered number is always identical to the original binary number and, if not always, in which cases it is not and how large can be the difference? I am particularly interested in the Put - Get cycle (on the same computer system).

The following two simple experiments show that probably the Put - Get cycle in Mathematica always restores original numbers exactly even for arbitrary precision numbers:

In[1]:= list=RandomReal[{-10^6,10^6},10000];
Put[list,"test.txt"];
list2=Get["test.txt"];
Order[list,list2]===0
Order[Total@Abs[list-list2],0.]===0

Out[4]= True
Out[5]= True


In[6]:= list=SetPrecision[RandomReal[{-10^6,10^6},10000],50];
Put[list,"test.txt"];
list2=Get["test.txt"];
Order[list,list2]===0
Total@Abs[list-list2]//InputForm

Out[9]= True
Out[10]//InputForm=
0``39.999515496936205

But maybe I am missing something?


UPDATE

With more correct test code I have found that in reality these tests show only that restored numbers have identical binary RealDigits but their Precisions may differ even in Equal sense. Here are more correct tests:

test := (Put[list, "test.txt"];
  list2 = Get["test.txt"];
  {Order[list, list2] === 0,
   Order[Total@Abs[list - list2], 0.] === 0,
   Total[Order @@@ RealDigits[Transpose[{list, list2}], 2]],
   Total[Order @@@ Map[Precision, Transpose[{list, list2}], {-1}]],
   Total[1 - Boole[Equal @@@ Map[Precision, Transpose[{list, list2}], {-1}]]]})

In[8]:= list=RandomReal[NormalDistribution[],10000]^1001;
test
Out[9]= {False,True,0,1,3}
In[6]:= list=RandomReal[NormalDistribution[],10000,WorkingPrecision->50]^1001;
test
Out[7]= {False,False,0,-2174,1}
like image 564
Alexey Popkov Avatar asked Jun 26 '11 07:06

Alexey Popkov


1 Answers

I'm afraid I can't give a definitive answer. If you look into the text file you see it's stored as something like the InputForm of the values, including the precision indication for non-machine precision numbers.

Assuming that Get uses the same conversion routines as ImportString and ExportString your test can be sped up a tiny bit.

Monitor[
 Do[
  i = RandomReal[{$MinMachineNumber, 10 $MinMachineNumber}, 100000];
  If[i =!= 
    ToExpression[ImportString[ExportString[i, "Text"], "List"]], 
   Print[i]], {n, 100}
  ],
 n]

I have tested this for several hundreds of millions of numbers in various ranges between $MinMachineNumber and $MaxMachineNumber and I always get back the original numbers. It's no proof, of course, but it seems unlikely that you're going to see numbers for which this is not true if there are any (and in that case the difference would be so tiny as to be negligible).

like image 135
Sjoerd C. de Vries Avatar answered Oct 21 '22 09:10

Sjoerd C. de Vries