1

在尝试将 double 转换为文本的代码时,我将例程的结果与标准库中的结果进行比较。对于标题中的数字和格式,我的例程返回

0.0039062

libgcc printf 打印相同的结果。但是,Microsoft C++(构建工具 2019)说

0.0039063

我相信微软的图书馆是错误的,每轮甚至规则。我对吗?

4

1 回答 1

2

C 标准规定结果必须正确舍入,但并未明确说明舍入规则是什么。

一些初步准备: .00390625 = 2 -8double如果使用二进制或十进制格式,则可以精确表示,因为DECIMAL_DIG(在 中声明<float.h>)必须至少为 10,这意味着精度足以精确表示。(理论上, adouble可能有另一个基数,例如 3,然后 .00390625 不能完全表示。这个答案不讨论这种情况。)

C 2018 7.21.6.1 7 表示%.5g使用此数字的转换将使用该f样式。对于f样式,它表示“......该值被四舍五入到适当的位数。”</p>

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 实现。

因此,使用“最接近”方法将 .00390625 舍入到五个有效数字的行为在技术上并未由 C 标准指定。

于 2021-08-25T14:08:59.000 回答