输出应该是什么 printf("%.5g", 0.00390625)
What should be the output printf("%.5g", 0.00390625)
在试验将双精度转换为文本的代码时,我正在将例程的结果与标准库中的结果进行比较。对于标题中的数字和格式,我的套路returns
0.0039062
libgcc printf 打印出相同的结果。但是,Microsoft C++(构建工具 2019)说
0.0039063
我相信微软的库是有错误的,每轮都要平分。我说得对吗?
C 标准说结果必须正确舍入,但没有明确说明舍入规则是什么。
一些预备知识:.00390625 = 2−8 如果使用二进制或十进制格式,则可以在 double
中精确表示,因为 DECIMAL_DIG
(已声明in <float.h>
) 必须至少为 10,这意味着精度足以准确表示。 (理论上,double
可以有另一个基数,比如 3,那么 .00390625 就不能准确表示。这个答案不讨论这种情况。)
C 2018 7.21.6.1 7 表示使用此数字的 %.5g
转换将使用 f
样式。对于 f
样式,它表示“...该值四舍五入到适当的位数。”
C 2018 7.21.6.1 13 表示“对于 e
、E
、f
、F
、g
和 G
转换,如果有效小数位数最多DECIMAL_DIG
,则结果应该正确四舍五入……”五当然小于十,所以结果应该正确四舍五入。
“正确舍入”在 3.9 中定义为“根据当前舍入模式,在值上最接近结果格式的表示形式,结果将被赋予无限范围和精度”。对于 printf
转换,结果格式为十进制数字。这个定义有效地告诉我们转换中不应该有算术错误。
在5.2.4.2.2 9中,标准规定了一些舍入方法,包括“向零”、“最接近”、“向正无穷大”和“向负无穷大”,并允许实现定义其他舍入模式。在大多数情况下,舍入模式控制内置算术和强制转换运算符。但是,它还应该管理 printf
转换。 (理想情况下,它还会管理 sin
等数学库例程,但很少实现这些例程以遵守舍入模式。)
因此,“.0039063”的输出可能是使用“朝向正无穷大”的舍入模式产生的。但是,我假设您的 Microsoft 实现使用默认的“最接近”舍入模式。您可以通过打印 FLT_ROUNDS
来测试它; “到最近”为 1。
但是,C 标准没有具体说明“最接近”方法对关系的作用,只是附件 F 将其绑定到 IEEE-754 最接近方法,该方法解决了有利于候选人的关系甚至低位数。但是,附件 F 是可选的;使用它不需要 C 实现。
因此,C 标准在技术上并未指定使用“最接近”方法将 .00390625 舍入为五位有效数字的行为。
在试验将双精度转换为文本的代码时,我正在将例程的结果与标准库中的结果进行比较。对于标题中的数字和格式,我的套路returns
0.0039062
libgcc printf 打印出相同的结果。但是,Microsoft C++(构建工具 2019)说
0.0039063
我相信微软的库是有错误的,每轮都要平分。我说得对吗?
C 标准说结果必须正确舍入,但没有明确说明舍入规则是什么。
一些预备知识:.00390625 = 2−8 如果使用二进制或十进制格式,则可以在 double
中精确表示,因为 DECIMAL_DIG
(已声明in <float.h>
) 必须至少为 10,这意味着精度足以准确表示。 (理论上,double
可以有另一个基数,比如 3,那么 .00390625 就不能准确表示。这个答案不讨论这种情况。)
C 2018 7.21.6.1 7 表示使用此数字的 %.5g
转换将使用 f
样式。对于 f
样式,它表示“...该值四舍五入到适当的位数。”
C 2018 7.21.6.1 13 表示“对于 e
、E
、f
、F
、g
和 G
转换,如果有效小数位数最多DECIMAL_DIG
,则结果应该正确四舍五入……”五当然小于十,所以结果应该正确四舍五入。
“正确舍入”在 3.9 中定义为“根据当前舍入模式,在值上最接近结果格式的表示形式,结果将被赋予无限范围和精度”。对于 printf
转换,结果格式为十进制数字。这个定义有效地告诉我们转换中不应该有算术错误。
在5.2.4.2.2 9中,标准规定了一些舍入方法,包括“向零”、“最接近”、“向正无穷大”和“向负无穷大”,并允许实现定义其他舍入模式。在大多数情况下,舍入模式控制内置算术和强制转换运算符。但是,它还应该管理 printf
转换。 (理想情况下,它还会管理 sin
等数学库例程,但很少实现这些例程以遵守舍入模式。)
因此,“.0039063”的输出可能是使用“朝向正无穷大”的舍入模式产生的。但是,我假设您的 Microsoft 实现使用默认的“最接近”舍入模式。您可以通过打印 FLT_ROUNDS
来测试它; “到最近”为 1。
但是,C 标准没有具体说明“最接近”方法对关系的作用,只是附件 F 将其绑定到 IEEE-754 最接近方法,该方法解决了有利于候选人的关系甚至低位数。但是,附件 F 是可选的;使用它不需要 C 实现。
因此,C 标准在技术上并未指定使用“最接近”方法将 .00390625 舍入为五位有效数字的行为。