Convert floating point numbers to string like sprintf/fprintf?

I am trying to export some floating point numbers into a csv/txt file. I would like to have a efficient way to control the space between numbers as well as the accuracy of the numbers, as we do in C:

fprintf(
fname, "%9.5f, %9.5f, %9.5f, %9.5f, %d\n",
y[i][1], y[i][2], y[i][3], y[i][4], d[i]
);

Here "%9.5f" is exactly what I want to implement in Mathematica. I searched for hours and can not get a good solution. NumberForm and PaddedForm only change the printing format, while others like SetAccuracy does not control the spaces. Any ideas? Many thanks.

• Did any of the answers satisfied your need? There are things to do after your question is answered. It's a good idea to stay vigilant for some time, better approaches may come later improving over previous replies. Experienced users may point alternatives, caveats or limitations. New users should test answers before voting and wait 24 hours before accepting the best one. One weeks is enough wait. Participation is essential for the site, please do your part. Jul 9, 2018 at 22:34
• I just linked to my sprintf-like implementation as an answer to mathematica.stackexchange.com/a/246849/7936 May 29, 2021 at 10:25

The NumberFormoption NumberPadding does exactly what you want:

StringTemplate[", "] @@ (
NumberForm[#, {9, 5}, NumberPadding -> {" ", "0"}] & /@ {3.1, 5.1}
)

(* "    3.10000,     5.10000" *)

Mathematica has no real sprintf- or fprintf-equivalents. Others have asked about the problem.

We can, however, simulate sprintf format with Mathematica functions and a bit of manipulation. Here are some sample values to demonstrate the problems with direct use of NumberForm.

samples = {1.123, 12.12345, -12.12345, 123.12345,
1234.12345, -123.12345, -123.123455};

This is the expected result for samples using sprintf and %9.5f format.

1.123       "  1.12300"
12.12345    " 12.12345"
-12.12345   "-12.12345"
123.12345   "123.12345"
1234.12345  "1234.12345"
-123.12345  "-123.12345"
-123.123455 "-123.12346"

Let's try to create the same result in Mathematica. Unfortunately, NumberForm does not duplicate sprintf.

numberform =
ToString@NumberForm[#, {9, 5}, NumberPadding -> {" ", "0"}] & /@ samples;

The length of the NumberForm strings is 11, but the length of sprintf strings is 9 before overflow. A fix is to trim one or two leading blanks from the NumberForm strings with StringTrim. Here's a comparison of sprintf, using NumberForm alone, and combining StringTrim[#, RegularExpression["^ {1,2}"]] with NumberForm.

sprintf       NumberForm     StringTrim
"  1.12300"   "    1.12300"  "  1.12300"
" 12.12345"   "   12.12345"  " 12.12345"
"-12.12345"   "  -12.12345"  "-12.12345"
"123.12345"   "  123.12345"  "123.12345"
"1234.12345"  " 1234.12345"  "1234.12345"
"-123.12345"  " -123.12345"  "-123.12345"
"-123.12346"  " -123.12346"  "-123.12346"

To simulate how fprintf would work with some sample data, first, convert the floating-point values in y to sprintf format. Convert the value in d to a string with ToString[IntegerPart[d[[i]]]]. Next, separate the sprintf strings with comma and a space: ", ". Here are some sample values for y and d.

SeedRandom[1]
y = RandomReal[{-99, 99}, {1, 4}];
d = RandomInteger[10, 4];
i = 1;

floats = StringTrim[#, RegularExpression["^ {1,2}"]] & /@
(ToString@NumberForm[#, {9, 5}, NumberPadding -> {" ", "0"}] & /@
y[[i]]);

s = StringJoin[
Riffle[Flatten@{floats, ToString[IntegerPart[d[[i]]]]}, ", "]
];

s // InputForm

The result, s, simulates the output of sprintf("%9.5f, %9.5f, %9.5f, %9.5f, %d", ...).

" 62.84312, -76.93892,  57.32615, -61.81498, 3"

Finally, save the formatted values to a text file.