How to export data files using specific number format

This is a variant on Andre's solution (worked out before I noticed!). Anyway this takes the FORTRAN descriptor values as arguments.

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}]]

f77Eform[Pi, 16, 8] ->       "  0.31415927E+01"
f77Eform[-Sqrt[2], 16, 8] -> " -0.14142136E+01"
f77Eform[10^-4, 16, 8]    -> "  0.10000000E-03"
f77Eform[-10^6, 16, 8]    -> " -0.10000000E+07"

sanity check:

Max[Table[(Abs[{Read[StringToStream[f77Eform[#, 22, 14]], Number]/# - 
    1}]) &[RandomReal[{-1, 1}] 10^RandomReal[{-5, 5}]] , {1000}]]   -> 4.64073*10^-14

I must say as someone who works with Fortran quite a lot I have never needed to do this. Fortran can perfectly well read more generally formatted data. Unless you are stuck with legacy Fortran code that uses fixed field formatting for input don't bother.


Mathematica has so many output and formatting options, it's quite hard to piece all the bits together sometimes. Here's something I've managed to build by looking at the extensive documentation:

formattedData = Partition[
 StandardForm@
    PaddedForm[
    #,
    {16, 16},
    NumberFormat -> (StringJoin[#1, "E", #3] &)] 
   & /@ Flatten@data, 2];

This applies a format to each number and turns the whole list back into a table.

{{ 0.0000000000000000E, 0.0000000000000000E},
 { 0.0688287941758228E, 7.8480265933168900E-11},
 { 0.0075608357710283E, 9.3849677784910300E-8},
 { 0.2817481779372621E, 4.9262973903383610E-6},
 ...

Now you can export it, using the "FieldSeparators" option for the "Table" format:

Export["out.dat", formattedData, "FieldSeparators" -> "    "]

and your file is now in two columns, separated by four spaces:

 0.0000000000000000E     0.0000000000000000E
 0.0688287941758228E     7.8480265933168900E-11
 0.0075608357710283E     9.3849677784910300E-8
 0.2817481779372621E     4.9262973903383610E-6
 ...

However, to get precisely 16 digits in total, with 8 after the decimal point, you'll need to ask another question!


I find NumberForm, FortranForm ... not adequate for this problem.

This is how I would do it :

Treatment for one number :

toEString[dat_] := 
 If[dat == 0.,
  "0.0000000000000000E+00",
  MantissaExponent[dat] //
   With[{mantissa = #[[1]], exponent = #[[2]]},
     {
        If[mantissa < 0, "-", ""],
        "0.",
        ToString /@ 
         PadRight[First[RealDigits[mantissa, 10, Automatic]], 16, 0],
        If[exponent < 0, "E-", "E+"],
        ToString /@ IntegerDigits[exponent, 10, 2]
        } //
       Flatten //
      StringJoin] &
  ]

Concatenation of the whole in a string :

StringJoin[
 StringJoin[
    toEString[#[[1]]] <> "   " <> toEString[#[[2]]] <> "\n"] &  /@  
  data
 ]

enter image description here

and then export the string as text (with Export[fileName,the String,"Text"]).

I don't know what you expect if some numbers are < 0.