为什么0.1f的最后一个二进制位会四舍五入为1?

5
我在大学学习操作系统课程,最近学习了浮点数在内存中的表示方法。我们的作业是手动将浮点数(float)转换为它们的二进制表示形式。例如,200.0234375在经过漫长的转换过程后会变成01000011010010000000011000000000。其中一个问题是0.1f在内存中的表示方式。所以我完成了整个转换过程,得出了以下结果:00111101110011001100110011001100。根据我们目前所学的知识,这是正确的答案(我问了老师)。但是,在下一个问题中,我们被要求使用程序验证答案,看看0.1f的实际二进制表示形式。真正的表示形式是00111101110011001100110011001101。(注意最后一位)然后我们被要求猜测为什么会发生这种情况。我在转换数字时注意到了周期性的0011,由于最终的0后面的下一位将是1,我认为计算机会将最后的0四舍五入为1,这可以解释差异。所以,我的问题是,我正确吗?计算机是否基于使用23位尾数时的下一位来舍入最后一位? 这是一项作业,如果我错了,如果您能简单地指导我找到答案,我将不胜感激。此外,我无法通过使用我能想到的关键字进行谷歌搜索找到答案。如果这是一个重复的问题,请原谅我。

C++ 可能不是这里的正确关键字,但我真的不知道所有语言的行为是否相同... - Jesse Emond
4
IEEE标准(你可能正在参考的标准,尽管你的问题让我们猜测)实际上规定了几种不同的舍入模式,因此具体情况取决于这些细节。最坏的情况是检查你的平台文档。 - Kerrek SB
@Kerrek SB:但是我的回答部分正确吗?还是完全错误?我真的不知道该如何回答这个问题。 - Jesse Emond
0.1作为double类型的值是多少?当你截断这个double类型时,是否会得到带有额外位的值? - Martin York
显示剩余4条评论
4个回答

3
计算机在使用23位尾数时,是否基于下一位来四舍五入最后一位?
是的,当然。默认情况下,编译器和浮点算术系统会尝试给出正确舍入的结果。
打个比方,如果我让你将2/3写成三位小数,你会回答0.666还是0.667?应该是0.667,因为它更接近真实答案。

实际上,我希望你想要0.666,因为这是算术除法给出的前三位小数。 - Blindy
这样表达起来很有道理!谢谢。 - Jesse Emond

1

我不太确定如何在不直接给出答案的情况下指导您,但是是的,您正在处理它。IEEE标准包括针对这种舍入方式的具体规定。请查找“guard”、“round”和“sticky bits”。


1

这将取决于您的平台,特定的浮点硬件以及该硬件上的特定设置。

特别是在x86平台上,具体行为将取决于FPU或SSE控制字寄存器的内容。


1

有几种四舍五入模式。

您可以在wikipedia上了解相关信息。

这只是实现的问题。C++没有对此进行规定。


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