Why does printf (Unix) use round half down? Why does printf (Unix) use round half down? unix unix

Why does printf (Unix) use round half down?


It's not strictly round-down:

> printf '%.0f\n' 2.52> printf '%.0f\n' 3.54

This is a form of rounding used to combat bias if you are rounding a large number of values; roughly half of them will be rounded down, the other half rounded up. The rule is, round down if the integer portion is even, up if the integer portion is odd.


This is, however, only an explanation of a particular rounding scheme, which is not guaranteed to be used by all implementations of printf.


From the POSIX specification for the printf command:

The floating-point formatting conversion specifications of printf() are not required because all arithmetic in the shell is integer arithmetic. The awk utility performs floating-point calculations and provides its own printf function. The bc utility can perform arbitrary-precision floating-point arithmetic, but does not provide extensive formatting capabilities. (This printf utility cannot really be used to format bc output; it does not support arbitrary precision.) Implementations are encouraged to support the floating-point conversions as an extension.

Thus: %f isn't even required to exist at all; anything it may or may not do is entirely unspecified by the relevant standard.


Similarly, there's no guidance on rounding provided on the POSIX standard for the printf() function:

f, F

The double argument shall be converted to decimal notation in the style "[-]ddd.ddd", where the number of digits after the radix character is equal to the precision specification. If the precision is missing, it shall be taken as 6; if the precision is explicitly zero and no '#' flag is present, no radix character shall appear. If a radix character appears, at least one digit appears before it. The low-order digit shall be rounded in an implementation-defined manner.

A double argument representing an infinity shall be converted in one of the styles "[-]inf" or "[-]infinity"; which style is implementation-defined. A double argument representing a NaN shall be converted in one of the styles "[-]nan(n-char-sequence)" or "[-]nan"; which style, and the meaning of any n-char-sequence, is implementation-defined. The F conversion specifier produces "INF", "INFINITY", or "NAN" instead of "inf", "infinity", or "nan", respectively.