当执行 printf("%.15e", 1e23); 时,会打印什么内容?

8

我正在尝试优化双文本转换(试图打败grissu、ryu等人)。

在此过程中,我正在将我的结果与sprintf输出进行比较。现在我遇到了上面这个有趣的情况。

printf("%.15e", 1e23);

例如glibc)打印
我的程序打印
这两个数字与“真实值”的距离相同,将这两个值都转换回来(例如使用`atof`)会产生相同的双精度浮点数。
然而,我认为我的结果满足“银行家舍入规则”(这也是导致结果如此的原因)。
哪个结果更正确?

1
看到一个关于浮点数的问题,而不仅仅是“浮点数计算是否有问题”的变体,真是让人耳目一新啊!;-) 不好意思,我不知道答案。 - Joachim Sauer
@DavidRanieri 来自 printf - Antti Haapala -- Слава Україні
1
@AdrianMole 不是这样。准确的值是0x1.52d02c7e14af6p+76。 - Antti Haapala -- Слава Україні
@AnttiHaapala 哦,好的,我以为你是想要类似于“gdb > print 1e23 以某种精度打印”的东西,谢谢 :) - David Ranieri
@AnttiHaapala 好的,我明白了。使用.30e精度打印显示为9.999999999999999161139200000000e+22 - Adrian Mole
显示剩余4条评论
1个回答

5

1e23通常不能被准确表示为double

最接近的两个选择是:

// %a           v     %f 
0x1.52d02c7e14af6p+76  99999999999999991611392.000000
0x1.52d02c7e14af7p+76 100000000000000008388608.000000

有两个数字:8388608.0 和 100000000000000000000000.0,一个在上面,一个在下面。

通常,在并列情况下选择偶数。(参见十六进制格式中的最后一位。)

99999999999999991611392.000000是获胜者,因此预计输出为"9.999999999999999e+22"

当使用更多的DBL_DIG(15)有效数字进行打印时,("%.15e"打印16个有效数字),这个问题是可能的,因为代码实际上正在执行文本-double-文本往返,并超过了double可以往返的范围。


我正在尝试优化双文本转换。建议使用"%a"以获得更深入的理解。

谢谢你的分析。结果选择另一个值是我的算法的产物 - 它基于将该值转换为整数(具有相应数量的数字),并使用“二进制”规则进行四舍五入 - 因此那个...1611.. 部分将其舍入。回到起点 :) - Mirek Fidler
@MirekFidler 一旦工作正常,请考虑 https://codereview.stackexchange.com - chux - Reinstate Monica
1e22通常是可以在“double”中编码的最高2次幂。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接