在 Mathematica 中,与其他计算机数学系统一样,数字在内部以二进制形式存储。但是,当使用Put
和PutAppend
等函数导出它们时,它们将转换为近似小数。当您使用Get
等函数导回它们时,它们将从此近似十进制表示形式恢复为二进制形式。
问题是恢复的数字是否总是与原始二进制数相同,如果不是总是,在哪些情况下不是,差异有多大?我对Put
- Get
周期(在同一台计算机系统上)特别感兴趣。
以下两个简单的实验表明, Mathematica 中的Put
- Get
周期可能始终精确恢复原始数字,即使对于任意精度数字也是如此:
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
但也许我错过了什么?
使用更正确的测试代码,我发现实际上这些测试只显示已恢复的数字具有相同的二进制RealDigits
,但即使在Precision
意义上,它们的Equal
也可能不同。这是更正确的测试:
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}
答案 0 :(得分:5)
恐怕我无法给出明确的答案。如果查看文本文件,您会看到它存储为值的InputForm,包括非机器精度数字的精度指示。
假设Get
使用与ImportString
和ExportString
相同的转换例程,您的测试可以加快一点。
Monitor[
Do[
i = RandomReal[{$MinMachineNumber, 10 $MinMachineNumber}, 100000];
If[i =!=
ToExpression[ImportString[ExportString[i, "Text"], "List"]],
Print[i]], {n, 100}
],
n]
我已经在$ MinMachineNumber和$ MaxMachineNumber之间的各种范围内对数以亿计的数字进行了测试,我总是得到原始数字。当然,这并不是证据,但是你似乎不太可能看到数字,如果有的话,这是不正确的(在这种情况下,差异将微不足道,可以忽略不计)。
答案 1 :(得分:0)
要知道的一件重要事情是Put [] / Get []不会保持打包数组。你应该看看DumpSave []。它更快,因为它是二进制格式并保持数组打包。