# Changing the format string for numeric floating point values in the Put function

In my current macro, I have:

Put[Chop[someList], "someFile"];


where "someList" is a mixed bag of "strings", "integers", "exact complex values" (e.g. (-1)^(1/3)) and "numeric floating point complex values". The Chop function nicely cleans all numeric elements which are close to zero. I am now looking for a way to specify the format string for non-zero "numeric floating point values", which would output at most some number of "significant" decimal digits (e.g. 7, instead of the default 17).

An example of my "someList":

someList = {{{"a string"}, {1, 2}}, {{3, 4}, {Exp[I/3], (-1)^(2/3)}}, {{5, 6}, {1.23456789 + 9.87654321*I, -9.87654321 + 1.23456789*I}}};


for which, I would like to get (assuming 6 "significant digits"):

{{{"a string"}, {1, 2}}, {{3, 4}, {E^(I/3), (-1)^(2/3)}}, {{5, 6}, {1.23457 + 9.87654*I, -9.87654 + 1.23457*I}}}


Update (2019.08.14): It seems that, despite repeated requests that can be found in the Internet, Mathematica does not provide any C-like "printf" (low level) formatted output conversion functionality. For the time being, I (mostly) solved my problem by using this trick:

InexactToExact[x_Real] :=
Which[PossibleZeroQ[Chop[FullSimplify[x]]], 0,
PossibleZeroQ[Chop[FullSimplify[x - 1]]],  1,
PossibleZeroQ[Chop[FullSimplify[x + 1]]], -1,
PossibleZeroQ[Chop[FullSimplify[x - 3]]],  3,
PossibleZeroQ[Chop[FullSimplify[x + 3]]], -3,
PossibleZeroQ[Chop[FullSimplify[x - 1/3]]],  1/3,
PossibleZeroQ[Chop[FullSimplify[x + 1/3]]], -1/3,
PossibleZeroQ[Chop[FullSimplify[x - Sqrt]]],  Sqrt,
PossibleZeroQ[Chop[FullSimplify[x + Sqrt]]], -Sqrt,
PossibleZeroQ[Chop[FullSimplify[x - Sqrt/3]]],  Sqrt/3,
PossibleZeroQ[Chop[FullSimplify[x + Sqrt/3]]], -Sqrt/3,
(* and so on for any "special" real value that you need *)
True, x] (* all another real values *)
InexactToExact[z_Complex] :=
Which[PossibleZeroQ[Chop[FullSimplify[z]]], 0,
PossibleZeroQ[Chop[FullSimplify[z - (-1)^(1/3)]]],  (-1)^(1/3),
PossibleZeroQ[Chop[FullSimplify[z + (-1)^(1/3)]]], -(-1)^(1/3),
PossibleZeroQ[Chop[FullSimplify[z - (-1)^(1/3)*Sqrt]]],  (-1)^(1/3)*Sqrt,
PossibleZeroQ[Chop[FullSimplify[z + (-1)^(1/3)*Sqrt]]], -(-1)^(1/3)*Sqrt,
PossibleZeroQ[Chop[FullSimplify[z - (-1)^(1/3)/Sqrt]]],  (-1)^(1/3)/Sqrt,
PossibleZeroQ[Chop[FullSimplify[z + (-1)^(1/3)/Sqrt]]], -(-1)^(1/3)/Sqrt,
(* and so on for any "special" complex value that you need *)
InexactNumberQ[z], FullSimplify[(InexactToExact[Re[z]]) + (InexactToExact[Im[z]]) * I],
True, z] (* all another complex values *)
InexactToExact[v:Except[_Real | _Complex]] := v (* all another types of values *)

someList = Replace[Chop[FullSimplify[someList]], {v_:>InexactToExact[v]}, {-1}];
Put[someList, "someFile"];


Unfortunately, the above trick does not work for many "exact" values. It seems to me that the problem is that Mathematica returns "Complex" for Head[3+I] and Head[3*I] but it happily returns "Plus" and "Times" for, respectively, Head[Sqrt+I] and Head[Sqrt*I].

• NumberForm[#,{\[Infinity],7}] or the same with DecimalForm, which gives only decimal form without scientific notation.
– Alx
Aug 5, 2019 at 9:19
• Thanks. I tried Put[NumberForm[Chop[someList], {\[Infinity],7}], "someFile"]; but, in the file, it simply saves "NumberForm[originalText, {\[Infinity],7}]". Aug 5, 2019 at 9:46
• Yu may use Export function: Export["somefile",Map[NumberForm[Chop[#], {\[Infinity], 7}] &,Table[{x, x^2, Sin[x]}, {x, 0, \[Pi], 0.1}],{2}],"Table"]. I used generated table here to show exporting to file with 3 columns of numbers of desired form.
– Alx
Aug 5, 2019 at 10:15
• Thanks again. It still doesn't work, sorry (I added an example of my "someList" above and, as one can see, I would need a solution which automatically deals with nested lists of different kinds of elements). Another problem with NumberForm is that it always outputs all "requested" digits, including the trailing zeros (e.g. one gets 0.0000000 instead of simply 0.). Aug 5, 2019 at 10:47
• I think I would need a way to modify the "format string" for the lowest level routine which writes numeric floating point values in the InputForm (used by the Put function). Aug 5, 2019 at 11:21

Updated to handle numbers in scientific notation

You could block the formatting of Real objects:

Block[{Real},
Format[r_Real, InputForm] := StandardForm @ NumberForm[
r,
3,
NumberFormat -> (Replace[#3, {"" -> #1, _ -> StringJoin[#1, "*^", #3]}]&)
];
Put[someList, "tstfile.txt"]
]


Check:

Import["tstfile.txt"]


"{{{\"a string\"}, {1, 2}}, {{3, 4}, {E^(I/3), (-1)^(2/3)}}, {{5, 6}, {1.23 + 9.88*I, -9.88 + 1.23*I}}}"

• @WileE. See update. Aug 14, 2019 at 17:37
• Thanks. I decided to go one step further and convert "inexact" numbers into "exact" ones (see my "update" above). Fortunately, I only need to deal with several tens of various "magic" values. Aug 14, 2019 at 18:28