【问题标题】:Why is printf round floating point numbers up?为什么 printf 舍入浮点数?
【发布时间】:2022-04-22 19:09:53
【问题描述】:

我正在尝试使用printf 打印一些浮点数。 例如:

int main()
{
    printf("%.1f",76.75); 
    return 0;
}

输出:76.8

我对结果有一些疑问。

首先,为什么不打印76.7

第二,如何四舍五入?

【问题讨论】:

  • 为什么要打印 76.7?
  • @ecatmur:该问题的答案归咎于浮点舍入错误,但这是另一种情况,因为数字 76.75 被精确表示。
  • FWIW,你的标题是:“为什么 printf 对浮点数进行舍入?”。好吧,因为你告诉它,使用 %.1f 格式化字符串。
  • @RudyVelthuis 这个问题是“为什么37.975 不能转换为 37.98?”。这个问题是“为什么76.75 转换为 76.8?”。它们是对称对立的问题。此外,那里的答案归咎于在编译37.975 期间发生的十进制到浮点 转换中的舍入。这里的正确答案应该说明这是 floating-point-to-decimal 转换的正常舍入行为,对于恰好介于两个十进制表示之间的值。
  • @Pascal:我现在明白了:接近投票。不,它不是重复的,IMO。

标签: c floating-point printf rounding


【解决方案1】:

C99 §7.19.6.1 fprintf 函数

f,F

表示浮点数的double 参数转换为[−]ddd.ddd 样式的十进制表示法,其中小数点字符后的位数等于精度规范。如果精度缺失,则取6;如果精度为零且未指定# 标志,则不会出现小数点字符。如果出现小数点字符,则在其前面至少出现一位数字。 该值四舍五入到适当的位数。

【讨论】:

    【解决方案2】:

    除了现有的答案,请注意许多 C 编译器尝试遵循 IEEE 754 处理浮点问题。 IEEE 754 建议根据当前舍入模式进行舍入,以便从二进制浮点数转换为十进制数。默认的舍入模式是“四舍五入到最接近并与偶数相关”。一些编译平台不考虑舍入模式,在浮点到十进制的转换中总是按照默认的最接近偶数模式进行舍入。

    由于76.75 正好代表数字 7675/100,它正好在 76.7 和 76.8 之间。在应用“四舍五入到最接近的偶数”时,后一个数字被认为是“偶数”。这可能是您的编译平台选择生成此十进制表示作为浮点数76.75 的十进制转换的原因。

    【讨论】:

    • 我从未见过printf按照当前的舍入模式进行舍入。 (不过,我已经有好几年没看过了。我所看到的只是四舍五入和 Java 的四舍五入。)哪些实现可以做到这一点?
    • @tmyklebu Mac OS X。Linux 总是舍入到最接近的偶数,即使舍入模式已更改。 pastebin.com/p3myWBQU(在 Mac OS X 上获得)。微软的编译器比舍入方向有更大的问题,所以我认为没有人关心这个。
    • @tmyklebu:总是愿意学习新东西,那么究竟什么是round-to-Java?有链接吗?
    • @RudyVelthuis:我记得,它总是向上取整“1/2”。即,System.out.printf("%.2f", 0.745); 输出0.75,即使double 0.745` 严格小于有理数745/1000
    • @tmyklebu 这是一个不好的例子,因为0.745 并不准确。或者它可能是“Java 舍入”的一个很好的例子,因为 Java 将它与%.53f 完全一样地打印出来。因此,“Java 舍入”实际上看起来是“打印所需数量的小数,以使原始浮点类型中的值明确,然后应用小学的舍入规则”。 0.745 小于 745/1000 并四舍五入为 0.75。杰出的!无论如何,如果你不想讨论为什么 Java 是 ,一个更好的例子是 0.25
    【解决方案3】:

    首先,他为什么不打印 76.7?

    因为语言规范说低位数字会被四舍五入。

    他是如何四舍五入的? (一些代码会有所帮助)

    这因实现而异。根据documentation

    低位数字应以实现定义的方式(添加强调)进行四舍五入。

    【讨论】:

      猜你喜欢
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多