printf()
function (whose functionality was copied into many programming languages).
It has several so-called “format directives” to specify how to print a (numerical) data type.
The format directives can be augmented with a field width, that specifies how many characters should be printed,
and a precision, that specifies the number of fractional digits.
The format directives can be look like this: %10.3f
which means: "3 fractional digits, 10 characters at all (incl. decimal point)".
Smaller numbers will be padded with blanks at the left, but bigger numbers will exceed the specified field width without warning!
For floating point types there are 3 different format directives that generate decimal output of the value:
%f
, %e
and %g
. Unfortunately none of them is able to print a floating point number in a sensible way (which means:
without loss of precision, but in the shortest form, see below). (The directive %a
which produce a hexadecimal output of a floating point value
is completely sane and works without problems)
To show how complex, but still imperfect the format directives works, let's have a look into the man page printf(3)
:
- f, F
- The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimalpoint character appears. If a decimal point appears, at least one digit appears before it.
- e, E
- The double argument is rounded and converted in the style [-]d.ddde±dd where there is one digit before the decimal-point character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An
E
conversion uses the letterE
(rather thane
) to introduce the exponent. The exponent always contains at least two digits; if the value is zero, the exponent is 00.- g, G
- The double argument is converted in style f or e (or F or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.
f
represents an interval I
of real numbers: all that real numbers
that are rounded to f
. There are several standardized rounding models („round to zero“,
„round to nearest“ etc.) so the particular interval might differ a bit, depending on the rounding model.f
.f
.f
?
If anyone has ideas, algorithms or ready-to-use C or C++ libraries to get this number,
please e-mail me.
n | Bits | %a | %.17g |
---|---|---|---|
0 | 0000000000000000000000000000000000000000000000000000000000000000 | 0x0p+0 | 0 |
0.1 | 0011111110111001100110011001100110011001100110011001100110011010 | 0x1.999999999999ap-4 | 0.10000000000000001 |
0.111 | 0011111110111100011010100111111011111001110110110010001011010001 | 0x1.c6a7ef9db22d1p-4 | 0.111 |
+10 | 0100000000100100000000000000000000000000000000000000000000000000 | 0x1.4p+3 | 10 |
10.111 | 0100000000100100001110001101010011111101111100111011011001000110 | 0x1.438d4fdf3b646p+3 | 10.111000000000001 |
12345678901234567890 | 0100001111100101011010101001010100110001100111010110001111100001 | 0x1.56a95319d63e1p+63 | 1.2345678901234567e+19 |
Here are some papers and C++ source code I found: