我在输出 float 时遇到了一个烦人的问题。当我在 Windows 上以 2 个小数点的精度格式化 11.545 时,它输出“11.55”,正如我所期望的那样。但是,当我在 Linux 上执行相同操作时,输出为“11.54”!
我最初是在 Python 中遇到这个问题,但进一步调查表明差异在于底层 C 运行时库。 (两种情况下的体系结构都是 x86-x64。)运行以下 C 行在 Windows 和 Linux 上会产生不同的结果,这与在 Python 中的结果相同。
printf("%.2f", 11.545);
为了更清楚地说明这一点,我将数字打印到小数点后 20 位 ("%.20f"
):
Windows: 11.54500000000000000000
Linux: 11.54499999999999992895
我知道 11.545 不能精确存储为二进制数。因此,似乎正在发生的事情是 Linux 以尽可能高的精度输出它实际存储的数字,而 Windows 输出它的最简单的十进制表示形式,即。尝试猜测用户最有可能的意思。
我的问题是:是否有任何(合理的)方法来模拟 Windows 上的 Linux 行为?
(虽然 Windows 行为当然是直观行为,但在我的例子中,我实际上需要将 Windows 程序的输出与 Linux 程序的输出进行比较,而 Windows 是我唯一可以更改的。顺便说一下,我试图查看 printf
的 Windows 源代码,但执行 float->string 转换的实际函数是 _cfltcvt_l
并且它的源代码似乎不可用。 )
编辑:情节变厚了!关于这是由不精确表示引起的理论可能是错误的,因为 0.125 确实有一个精确的二进制表示,并且当使用 '%.2f' % 0.125
输出时它仍然不同:
Windows: 0.13
Linux: 0.12
但是,round(0.125, 2)
在 Windows 和 Linux 上都返回 0.13。
最佳答案
首先,在这种情况下,听起来 Windows 的错误是正确的(但这并不重要)。 C 标准要求 %.2f
输出的值四舍五入到适当的位数。最著名的算法是 dtoa由 David M. Gay 实现.您或许可以将其移植到 Windows 或找到 native 实现。
如果您还没有读过 Steele 和 White 的“如何准确打印 float ”,请找一本读一读。这绝对是一本启发性的读物。一定要找到 70 年代后期的原作。我认为我在某个时候从 ACM 或 IEEE 购买了我的。
关于python - 在 Windows 上模拟 Linux 的浮点字符串转换行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2234303/