为什么printf函数会将浮点数四舍五入?

24

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

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

输出:76.8

我对结果有一些问题。

首先,为什么它没有打印出76.7

其次,它是如何四舍五入的?


7
为什么应该打印76.7? - Jayesh Bhoi
4
那个问题的答案归咎于浮点数舍入误差,但这是一种不同的情况,因为数字“76.75”被准确地表示。 - dan04
就你的标题而言,“为什么printf会四舍五入浮点数?”嗯,因为你使用了“%.1f”格式化字符串告诉它这样做。 - Rudy Velthuis
2
@RudyVelthuis 那个问题是“为什么 37.975 不转换为 37.98?”这个问题是“为什么 76.75 转换为 76.8?”它们是对称的相反的问题。此外,那里的答案归咎于在编译 37.975 期间发生的 十进制到浮点数 转换中的四舍五入。正确的答案应该解释这是 浮点数到十进制 转换的正常舍入行为,对于一个恰好处于两个十进制表示之间的值。 - Pascal Cuoq
2
@Pascal:我现在看到了:关闭投票。不,依我之见,它不是重复的。 - Rudy Velthuis
显示剩余2条评论
3个回答

19

C99 §7.19.6.1 函数 fprintf

f,F

将浮点数 double 格式化为十进制小数表示形式,格式为 [−]ddd.ddd,小数点后的数字位数等于精度规范。如果省略了精度,则默认为6;如果精度为零并且未指定 # 标志,则不会出现小数点字符。如果出现小数点,则小数点之前至少出现一个数字。该值将四舍五入到适当的数字位数。


1
但是"rounded"是什么意思呢?一个天真的想法是它表示"到最近的整数",在0.5周围有一些余地,但请注意,C标准定义了四种不同的舍入模式(参见7.6),而核心标准拒绝指定默认值,因此不清楚"rounded"指的是其中哪一种。如果您认为它遵循舍入模式(标准不要求这样做),则会发现F.7.3(C99中的F.8.3)指定了默认舍入模式为"最近的整数"。 - Jordan Brown

15
除了现有的答案外,需要注意许多C编译器试图遵循IEEE 754关于浮点数的规范。IEEE 754建议将二进制浮点数转换为十进制时,根据当前舍入模式进行四舍五入。默认的舍入模式是“最接近偶数”的方式。一些编译平台不考虑舍入模式,在浮点数和十进制之间的转换中始终按照默认的最接近偶数模式进行四舍五入。
由于76.75恰好表示数字7675/100,它恰好位于76.7和76.8之间的中心位置。在应用“最接近偶数”舍入模式时,后者被认为是“偶数”。这可能是您的编译平台选择生成此十进制表示形式作为浮点数76.75的十进制转换的原因。

2
@tmyklebu Mac OS X。Linux总是四舍五入到最近的偶数,即使舍入模式已更改。http://pastebin.com/p3myWBQU(在Mac OS X上获得)。微软的编译器有比舍入方向更大的问题,所以我认为没有人关心那个。 - Pascal Cuoq
2
@tmyklebu:我总是乐于学习新的东西,那么什么是round-to-Java?你有链接吗? - Rudy Velthuis
据我回忆,它总是将“1/2”四舍五入为上。也就是说,即使“double 0.745”严格小于有理数“745/1000”,System.out.printf("%.2f", 0.745);输出0.75 - tmyklebu
@tmyklebu 这个例子不好,因为 0.745 不是精确的。或者这可能是“Java舍入”的一个很好的例子,因为Java使用 %.53f 打印它时会打印出精确值。因此,“Java舍入”实际上似乎是“打印足够多的小数位以使值在原始浮点类型中无歧义,然后应用小学的舍入规则”。0.745 小于 745/1000 并被舍入为 0.75。太棒了!无论如何,如果您不想讨论为什么Java <脏话蜂鸣器>,那么一个更好的例子是 0.25 - Pascal Cuoq
@PascalCuoq:这就是我选择0.745的原因。0.745-the-double小于0.745-the-rational,所以使用"%.2f"打印时,无论采用哪种最近舍入方式,它都应该向下舍入。但是Java使用"%.2f"将其向上舍入。 - tmyklebu
显示剩余5条评论

8

首先,为什么他没有打印出76.7?

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

他如何对数字进行舍入?(一些代码会有帮助)

这因实现而异。根据文档所述,

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


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