Formatting numbers when writing to files in Mathematica

This is a continuation of this question regarding number formatting and related to my previous question about getting a very specific Mathematica output for text files.

I often have to use high precision in Mathematica to generate data, but relatively low accuracy is required for visualization. I also want to save data for later use with all symbol names and array structures. I used Save[] , but there are two related problems.

  • High accuracy "pollutes" my results with extra numbers, which are very difficult to get rid of:

     In[1] := b = SetPrecision[7, 50]; a = Pi/b Out[1] := 0.44879895051282760549466334046850041202816705705358654585356351318683091518373`50. In[2] := InputForm @ N[a, 6] Out[2] := 0.44879895051282760549466334046850041203`6. 

    where I really need only 0.448799.

  • Sometimes even a number indicating accuracy is corrupted, and I get values ​​like 4.72642364528438598726943'5.9999999999999999999999 , where I usually don't need accuracy, and 4.72642 will be enough.

Both of these add significant overhead to file size, and while storage on the hard drive is cheap, file size is of utmost importance if you later upload the files back to Mathematica.

So, starting with, for example, aa , which contains 50 digits of arbitrary precision numbers in an irregular array, there is a built-in way to get a text file that will read something like this

 aa = {{2.0437`4, 4.7276`4, ...}, ...} 

EDIT . To clarify, I have no problem displaying numbers or tracking the accuracy of numbers or changing the accuracy of numbers. I am having problems controlling how a number is written to a file.

Using N , NumberForm , OutputForm , InputForm , *Form , etc., all do not work properly with Save . And Save is the only export parameter I can find that exports the structure of characters and arrays. Export and Put* can be used to better control formatting, but they do not include a character (and in the case of Export the array structure is also lost).

+6
precision wolfram-mathematica
source share
4 answers

Do you really need things like 2.0437`4, or is it enough to double the 2.0437 car? If the latter, then you can do something like

 N[SetPrecision[values,6]] 

to make machines double, which will (basically) show six decimal digits.

A possible advantage is its reading. Now your array will be doubled by the machine, and therefore packed. I'm not sure if Get or Import is automatically packaged, but Developer`ToPackedArray will do this.

--- edit 2011-02-11 ---

Now that I saw what could go wrong ...

Here is an example using your later input and a few others that I hope will be representative.

 aa = {7.469702041097916467293771347613073888816285869`15.\ 954589770191005*^-51, 5555.22222222222222222223, .00000000002222222222222222222222222227777777777777, N[E, 22]^33} 

First converted to a string. In fact, this may be all you really need to save to a file. I use NumberForm, but with a custom formatting function (trimmed by and large from the documentation pages).

 In[39]:= InputForm[ToString[ NumberForm[N[aa], 6, NumberFormat :> (If[#3 != "", Row[{#1, "*^", #3}], #1] &)]]] Out[39]//InputForm= "{7.4697*^-51, 5555.22, 2.22222*^-11, 2.14644*^14}" 

Note that expression conversion works just fine.

 In[40]:= InputForm[ToExpression[ ToString[NumberForm[N[aa], 6, NumberFormat :> (If[#3 != "", Row[{#1, "*^", #3}], #1] &)]]]] Out[40]//InputForm= {7.4697*^-51, 5555.22, 2.22222*^-11, 2.14644*^14} 

--- end of editing ---

Daniel Lichtblow Wolfram Research

+6
source share

Here is a very stupid way to do what I want, i.e. causing Mathematica to discard extra numbers.

 aa = {7.469702041097916467293771347613073888816285869`15.954589770191005*^-51, ...}; list = RealDigits[N[aa, 6]]; bb = Thread @ #1*10.^(#2 - #3) &[FromDigits /@ First /@ list, Last /@ list, First /@ Dimensions /@ First /@ list]; InputForm @ bb {7.469700000000001*^-51, ...} 

This is an improvement, but still has more than double the number of characters needed.

EDIT: And we have a winner:

 list = Transpose @ {FromDigits /@ First /@ #, Last /@ #, First /@ Dimensions /@ First /@ #}& @ RealDigits[N[aa, 6]]; bb = ToExpression[ToString[#1] <> ".*^" <> ToString[#2 - #3]] & @@@ list; InputForm @ bb {7.4697`*^-51, ...} 
+3
source share

OutputForm is your friend to get rid of extra digits. You can hack it into a string even though it's ugly

 f[x_,n_]:=StringJoin[ToString[OutputForm[N[x,n]]],"`",ToString[Round[Precision[N[x,n]]]]]; 

Alternatively, if you don't need backlinks or corrections, a simple solution:

 FormatList[l_,n_]:=OutputForm[N[#,n]]&//@l; 

Edit: The second solution does not seem to work; interim fix

 FormatList[l_,n_]:=OutputForm[N[#,n]&//@l]; 
0
source share

I do not have a direct solution for your problem, but I have a suggestion that may be useful in another way.

If you are interested in saving the state and definitions of a Mathematica session, you are often better off using DumpSave rather than Save . Instead of a regular text file, you get some kind of binary image, and not only does it usually use much less space, they load much, much, much faster. The main disadvantage is that the resulting files are not portable at all between versions of Mathematica or different OSs, or something like that, and they are clearly not human-readable.

You can also suppress return outputs and precision using the NumberMarks option with InputForm et al. If you are really interested in reducing accuracy, I think using N is the way to go.

0
source share

All Articles