# Save a fraction matrix in Mathematica into C++ friendly format

In MMA I have a 2d matrix whose each entry is a irrational number(in fraction format in MMA). Say:

{{-4,           -(2/Sqrt[5]),  0]},
{-(4/Sqrt[20]), -4,            -Sqrt[2]},
{1,            0,             0}}


Now I would like to convert it into decimals and save as much precision as possible before feeding it into C++.

I learnt that 16 significant decimal places is the limit of double precision in C++. So I would like to convert the matrix above into one with scientific notation with entries like:

1.1234567890123456E10


or

1.1234567890123456E-10


Then I can make the best use of 16 digits in the double precision and give the matrix directly to C++.

Here comes the question:

1. how could I convert the fractions into the "E" notation?

and

1. save the matrix in a plain text file friendly to the Eigen Library I'm using? See the format here: Example
matrix << 1,0,1,0,
1,0,1,0,
1,0,1,0,


I have tried ScientificForm but what was exported was like:

ScientificForm[-0.816496580927726]...


What if I just need the numbers in E notation?

• Something like CForm[\$MachineEpsilon]? – J. M.'s ennui May 9 '16 at 3:12
• @J.M. I tried CForm, FortranForm, the same as the ScientificForm[-0.816496580927726] – James LT May 9 '16 at 3:18
• That would be due to the fact that the number is not large enough or small enough to warrant scientific notation. Are you asking that numbers like 1.6 and -0.754 all be expressed scientifically, or do you have a minimum and maximum threshold? – J. M.'s ennui May 9 '16 at 3:21

You can use NumberFormat option in ScientificForm to do this. For example

cformat[x_, numDigts_] :=
ToString[
ScientificForm[x, numDigts, NumberFormat -> (Row[If[#3 == "", {#1}, {#1, "E", #3}]] &)]]


then

cformat[1.2345678*^-10, 4]
(* "1.235E-10" *)


However, since your data is all in the range of 0 to 10, there would be no "E" in the results:

data = {{-4, -(2/Sqrt[3]), 0}, {-(4/Sqrt[3]), -4, -Sqrt[2]}, {1, 0, 0}};
StringRiffle[StringRiffle[#, "\t"] & /@ Map[cformat[#, 10] &, N@data, {-1}], "\n"]

(*
-4. -1.154700538    0.
-2.309401077    -4. -1.414213562
1.  0.  0.
*)


If you like to make the format line up together nicely and always have the "E", here is a version modified from george2079's answer:

f77Eform[x_?NumericQ, fw_Integer, ndig_Integer] :=
Module[{sig, s, p, ps}, {s, p} = MantissaExponent[x];
{sig, ps} = {ToString[Round[10^ndig Abs[s]]], ToString[Abs[p]]};
StringJoin @@
Join[Table[" ", {fw - ndig - 7}],
If[x < 0, "-", " "], {"0."}, {sig},
Table["0", {ndig - StringLength[sig]}], {"E"},
If[p < 0, {"-"}, {"+"}], Table["0", {2 - StringLength[ps]}], {ps}]]

toCformat2D[A_, numDigts_: 8] := Module[{lth, lineToString},
lth = Length[A];
lineToString[ls_] := StringRiffle[ToString /@ f77Eform[#, 2*numDigts, numDigts] & /@ ls, "\t"];
StringRiffle[Table[lineToString[A[[n]]], {n, 1, lth}], "\n"]
]

toCformat2D[data, 10]
(*
"-0.4000000000E+01       -0.1154700538E+01        0.0000000000E-307
-0.2309401077E+01       -0.4000000000E+01       -0.1414213562E+01
0.1000000000E+01        0.0000000000E-307       0.0000000000E-307"
*)