I was trying a very simple printf
test:
printf "%.16f\n" 5.10
On linux I got this output: 5.100000000000000000
which is expected.
But the very same test on OS/X produces this: 5.0999999999999996
Why does printf
produce different output?
EDIT: This is not C code, printf
is also a command-line utility, handy for scripts and tests.
The equivalent C program below produces 5.100000000000000000
:
#include <stdio.h>
int main() {
printf("%.16f\n", 5.10);
return 0;
}
EDIT 2: The plot thickens... to make this more interesting for linux users, if I run this command as nobody
, I get the same behavior as on OS/X:
chqrlie$ printf "%.18f\n" 5.10
5.100000000000000000
chqrlie$ su nobody -c 'printf "%.18f\n" 5.10'
5.099999999999999645
If you use MacOS® X, you don't need to install a third-party client like PuTTY to connect to your cloud server by using Secure Shell (SSH). Terminal is a terminal emulation program included with MacOS X that you can use to run SSH.
Historically, the default shell for macOS was bash. But with the introduction of macOS Catalina Apple changed the default to zsh (zshell).
Both the GNU implementation and the MacOS (FreeBSD) implementation of printf
are different programs. Both aim to be compatible with the POSIX standard.
POSIX leaves the representation of floating point numbers open to the implementation of printf. Their argumentation is that all calculation in shell is integer anyway.
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.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
PS:
5.1
is not a floating point number in bash. bash does not support floating numbers.
5.1
is a string, interpreted by printf
depending on the locale(!)
theymann@theymann-laptop:~/src/sre/inventory-schema$ LANG=en_US.UTF8 printf "%.16f\n" 5.10
5.1000000000000000
theymann@theymann-laptop:~/src/sre/inventory-schema$ LANG=de_DE.UTF8 printf "%.16f\n" 5.10
bash: printf: 5.10: Ungültige Zahl. # << German: Bad Number
0,0000000000000000
Note: In Germany we use , as the decimal separator.
The difference in the output between a normal user and nobody must the shell which is used. some shells, like busybox come with their own implementation of printf
. Btw, I'm extremely surprised that nobody is allowed to execute commands on your system!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With