【问题标题】:Gaps between successive floating point numbers连续浮点数之间的间隙
【发布时间】:2015-03-26 11:42:27
【问题描述】:

(所有讨论的数字都是十进制)

假设我们有一个浮点数据类型,类似于:

m * 10 ^ e

where m is the mantissa . and max mantissa size is 1 ( 0 <= m <= 9);

e is the exponent and its size is  -1 <= e <= 1

我们说我们的数据类型最大值是90,最小值是0

但是:这并不意味着我们可以表示所有在此限制内的数字。 我们只能表示 27 个数字 (9 * 3),不包括零。

具体来说,我们不能用这种方式表示 89,因为它有一个两位数的尾数 (并且它们都不是零)。

在技术上类似于上述描述。在浮点数据类型中(在任何编程语言中),在 Max 和 Min 值之间必须有一些整数,我们不能将这些整数存储在浮点数据类型中。

是上述参数 sound 。如果是,请举例说明如何在 java 或 c 中显示这个?

【问题讨论】:

  • 当您说“在任何编程语言中”时,您的真正意思是“所有数字都是十进制”不再适用,并且您想推广到基数 2,对吧?

标签: numbers computer-science representation


【解决方案1】:

你的推理非常合理。最容易展示的就是做例子,就像你做的那样。

一个不可代表的例子

考虑IEEE-754定义的“通常的单浮点”格式,它有7个指数位,因此范围超出[-2^127,2^127]

它也有 24 个尾数位,所以让我们考虑一下 67108864、67108865 和 67108866。这些数字分别是 2^26、2^26+1 和 2^26+2。

尝试将它们规范化以将它们写入浮点格式,您会看到

  • 尾数取值为 26
  • 第一位消失了,因为在 IEEE-754 格式中,第一个数字总是* 1 是隐含的,所以每个数字只剩下 25 位
  • 所有接下来的位(在 24 位的限制内)组成尾数...
    • 67108864 的尾数只有零,因为它的最小位是 0,您可以删除它而不会丢失信息。
    • 67108866 在其尾数的最后位置有一个 1,因为它的最小位也是 0,您仍然可以删除它而不会丢失信息。
    • 67108865 只有零和 1 作为最小位,即超过 24 位!因此,数字将四舍五入为 2^26 或 2^26+2。

因此您有一个示例,例如 89 : 67108865 在浮点数中无法表示。


* 除了次正规,见下文(扩展评论)

偏差

确实,我在这里跳过了一部分。指数没有直接编码在为其保留的位中,它是有偏的。在单浮点的情况下,偏差为 127。

所以我们的 26 实际上由 26+127 表示,因此是 153。从维基百科中窃取以下图像:

如果你采用这些数字(符号、指数和尾数),并且想要表达一个非次正规数,你会得到:(-1)sign * 2( exponent-127) * 1.mantissa

次正规

一旦我们达到可能的最小指数,即一旦我们将它写为 0 并表示 -127,我们就停止假设初始 1。这样,我们可以表示小于 2 的数字-127 (通过牺牲精度,因为我们将在尾数上有前导 0)。

然后我们有:(-1)sign * 2-127 * 0.mantissa

特别是,当尾数全为 0 时,我们有 0,这是有意的:现在,二进制表示中只有 0 的数字被读取为 0。在某种程度上,0 是最小的次正规数(尽管在实践中人们认为它只是一个特例)。

其他特殊情况是指数全为 1。如果尾数全为 0,则您有 +/- 无穷大(取决于符号),如果设置了一些尾数位,则您有一个 NaN。

【讨论】:

  • 有些东西我不明白。如果假设每个二进制数的最高有效位为“1”,则:1.我们如何在 IEEE-754 中表示 0 2.如果是这种情况,那么我们将能够保存 2^24+1(十进制: 16777217 / binary : 10000000000000000000000001 )在浮点数但我们不能(当我在java中测试它时它被四舍五入到16777216)
  • @kiyarash 我在答案中更新了这一点,尽管它超出了问题的范围。大多数参考文献都很模糊,但是我会推荐这个介绍:steve.hollasch.net/cgindex/coding/ieeefloat.html
【解决方案2】:

是的,您的推理是正确的,应该很容易找到无法用您的数据类型表示的实数。

考虑您允许的最小尾数 (0) 和指数 (-1):

0 * 10 ^ -1

= 0.0

您允许的下一个更高的尾数是 1:

1 * 10 ^ -1

= 0.1

您不能表示 0.0 和 0.1 之间的任何实数,例如 0.05。

您应该能够用 Java 或 C 来表达这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-27
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 2019-10-02
    相关资源
    最近更新 更多