Formatting numbers when writing to files in Mathematica

泪湿孤枕 提交于 2020-01-13 09:54:13

问题


This is a continuation of this question regarding number formatting, and related to my earlier question about obtaining very specific Mathematica output to text files.

I frequently have to use high precision in Mathematica for data generation but only need relatively low precision for visualization purposes. I also want to store the data for later use with all Symbol names and Array structures intact. For this I have been using Save[], but there are two related problems.

  1. The high precision "pollutes" my results with superfluous digits which are very hard 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 only need 0.448799.

  2. Sometimes even the number indicating precision is corrupted and I get values like 4.72642364528438598726943'5.9999999999999999999999 where I don't generally need the precision and 4.72642 would suffice.

Both of these introduce significant overhead to the file size, and while hard disk storage is cheap, file size makes a huge difference when later loading the files back into Mathematica.

So, starting with, e.g., aa that contains 50 digit arbitrary precision numbers in an irregular array, is there a built in way for me to get a text file that would read something like this

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

EDIT: To clarify, I am not having problems with the display of numbers or with tracking the precision of numbers or with changing the precision of numbers. What I am having trouble with is 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 exporting option I can find that exports the symbol and array structure. Export and Put* can be used to control the formatting better but they don't include the symbol (and in the case of Export the array structure is lost as well).


回答1:


Do you really require things like 2.0437`4, or would the machine double 2.0437 suffice? If the latter then you could do something like

N[SetPrecision[values,6]]

to coerce to machine doubles that will (mostly) show six decimal digits.

An possible advantage is in reading back it. Your array will now be machine doubles, hence packable. I'm not sure if Get or Import automatically pack, but Developer`ToPackedArray will do that.

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

Now that I've seen what can 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 convert to a string. This may actually be all you really want, for purposes of saving to a file. I use NumberForm, but with a custom formatting function (cribbed by and large from 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}"

Notice that the expression conversion works fine on this.

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 edit---

Daniel Lichtblau Wolfram Research




回答2:


Here is a very kludgy way of doing what I want, i.e., forcing Mathematica to discard superfluous digits.

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, ...}

Which is already an improvement but still has more than two times the character count of what is necessary.

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:


I don't have a direct solution to your problem, but I do have a suggestion that may be helpful in other ways.

If you're interested in saving Mathematica session state and definitions, you're often better off using DumpSave as opposed to Save. You get some sort of binary image instead of a plain text file, and not only does it typically use much less space, they load much, much, much faster. The main drawback is the resulting files aren't at all portable between versions of Mathematica, or different OSes, or anything like that, and they obviously aren't human readable.

You can also suppress the backticks and precision by using the NumberMarks option with InputForm et al. If you're actually interested in reducing the precision, I think using N is the way to go.




回答4:


OutputForm is your friend for getting rid of extra digits. You could hack it into a string, although it is ugly

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

Alternatively, if you don't need the backticks or precisions, the simple solution is:

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

Edit: The second solution doesn't seem to work; provisional fix is

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


来源:https://stackoverflow.com/questions/4955429/formatting-numbers-when-writing-to-files-in-mathematica

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!