为什么我在Linux和OS / X上得到不同的输出

时间:2019-04-12 07:50:48

标签: c linux macos printf sh

我正在尝试一个非常简单的printf测试:

printf "%.16f\n" 5.10

在linux上,我得到了以下输出:5.100000000000000000

但是在OS / X上进行的完全相同的测试会产生以下结果:5.0999999999999996

为什么printf会产生不同的输出?

编辑:这不是C代码,printf也是命令行实用程序,非常适合脚本和测试。

以下等效的C程序产生5.100000000000000000

#include <stdio.h>

int main() {
    printf("%.16f\n", 5.10);
    return 0;
}

编辑2 :该图变厚了……使这对Linux用户更加有趣,如果我以nobody的身份运行此命令,则会得到与OS / X相同的行为:

chqrlie$ printf "%.18f\n" 5.10
5.100000000000000000
chqrlie$ su nobody -c 'printf "%.18f\n" 5.10'
5.099999999999999645

2 个答案:

答案 0 :(得分:8)

printf的GNU实现和MacOS(FreeBSD)实现都是不同的程序。两者都旨在与POSIX标准兼容。

POSIX使浮点数的表示形式对printf的实现开放。他们的论点是,shell中的所有计算无论如何都是整数。

  

因为外壳程序中的所有算术都是整数算术,所以不需要printf()的浮点格式转换规范。 awk实用程序执行浮点计算并提供其自己的printf函数。 bc实用程序可以执行任意精度的浮点运算,但不能提供广泛的格式化功能。 (此printf实用程序实际上不能用于格式化bc输出;它不支持任意精度。)鼓励实现支持将浮点转换作为扩展。

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html


PS:

5.1

不是bash中的浮点数。 bash不支持浮点数。

5.1是一个字符串,由printf解释,取决于语言环境(!)

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

注意:在德国,我们使用,作为小数点分隔符。


普通用户与没有人必须使用的外壳之间的输出差异。有些shell(例如busybox)带有自己的printf实现。顺便说一句,我非常惊讶没有人被允许在您的系统上执行命令!

答案 1 :(得分:3)

这是因为浮点类型大多不能表示精确值。例如,使用在线IEE754工具,您会得到:

enter image description here

因此5.1不能用这种格式精确表示。

然后printf(或其他任何内容)可以自由格式化/打印任何它认为适合用户的值。