C语言中浮点数取整问题

6

我想了解浮点数的工作原理。

我希望通过以下方式测试我的知识/需要学习的内容:我想找到最小的x,使得x + 1 = x,其中x是一个浮点数。

据我所知,当x足够大时,x+1会更接近于x而不是下一个可由浮点表示的比x更高的数字。因此,直觉上似乎情况是我在有效数字中没有足够的位数。那么这个x的值是否是所有有效数字都是1的数字?但是我似乎无法确定指数应该是多少。显然,它必须很大(相对于10的0次幂)。


2
就像你所问的那样,负无穷大 :-) 你可能想要最小的正数而不是最小的数。 - AProgrammer
3个回答

5
您只需要用指数表达尾数中LS位的值。当这个值大于1时,您就满足了条件。对于单精度浮点数,LS位的值为2^-24*2^exp,因此当exp>24时,条件就会满足,即25。因此,满足此条件的最小(规格化)数字将是1.0 * 2^25 = 33554432.0f。
我没有检查过这个公式,所以我的数学可能有误(例如乘以2的因素),并且FP单元可能会在第24位之后进行舍入,因此可能需要进一步考虑乘以2的因素,但您已经得到了一个大致的想法...

1
哦,伙计,我刚好在你发布这个帖子的时候弄明白了!太棒了! - Tony Stark
1
实际上,x=2^24是第一个满足条件的浮点数(任何大于2^24-1的值都需要25位,因此超出了浮点数的精确表示范围)。 - Rick Regan
1
可能有一些粘着位超出了你看到的尾数,用于四舍五入,所以取决于数字如何进入寄存器(通过 int 转换为 float 或通过 float + float(1.0) 等),可能会有微妙的差异,因此它可能是24或25或26位,但在那个范围内,你将其推出尾数的末尾。 - old_timer
1
@dwelch:我非常确定它会在25位数范围内发生;如果不是2^24(在我的测试中它适用于2^24),那么很快就会发生。25位整数必须舍入为偶数(16777216、16777218、16777220、16777222等),因此这些是x的候选值。你必须比所有2^23个加1的数都舍入到x更不幸才行! - Rick Regan
1
我会假设一些浮点处理器在这方面有所不同,我已经很久没有查看规格以了解其详细信息。从理论上讲,您需要至少再增加一个位来进行舍入。回答具体问题还取决于X和舍入,1加上正确的数字将舍入到尾数,而其他舍入模式则不会。也许我们已经过度强调指数尾数的事情,帖子作者已经足够理解了。 - old_timer
显示剩余5条评论

0

从1.0开始,不断加倍直到测试成功:

double x;
for (x = 1.0; x + 1 != x; x *= 2) { }
printf("%g + 1 = %g\n", x, x + 1);

尝试并不意味着我理解了其中的原因 :) 我更倾向于先推理一下。我想这篇文章更普遍地讨论了舍入是如何融入浮点数学中的,正如我提出的示例问题所证明的那样。 - Tony Stark

0

我建议在尝试理解浮点数和浮点算术时,使用十进制,其中有效数字为5位,指数为2位。(或者,如果5和2不适合您,可以选择6和3或其他您喜欢的小数字。)以下问题:

  • 可表示的数字集合有限;
  • 非交换性、非结合性和非分配性;
  • 将浮点数视为实数时可能出现的问题;

在十进制中,所有这些问题都更容易理解,所学到的教训是完全通用的。一旦您掌握了这个知识点,通过IEEE浮点算术来增强您的知识将相对容易。您还将能够相对轻松地理解其他浮点算术系统。


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