在16,32和64位IEEE-754系统中可以表示的范围是什么?

我知道一些关于如何表示浮点数的知识,但恐怕还不够。

一般的问题是:

对于一个给定的精度(对于我来说,基数为10的精确小数位数),对于16,32和64位IEEE-754系统,可以表示什么范围的数字?

具体来说,我只对16位和32位数的范围精确到+/- 0.5(1位)或+/- 0.0005(千位)感兴趣。

我从MATLAB文档中为EPS函数绘制了这个答案,但它应该普遍适用于IEEE-754浮点数。

对于给定的浮点数X ,如果

2^E <= abs(X) < 2^(E+1) 

那么从X到下一个最大可表示浮点数( ε )的距离是:

 epsilon = 2^(E-52) % For a 64-bit float (double precision) epsilon = 2^(E-23) % For a 32-bit float (single precision) epsilon = 2^(E-10) % For a 16-bit float (half precision) 

上面的等式允许我们计算以下内容:

  • 对于半精度 …

    如果你想要一个+/- 0.5(或2 ^ -1)的准确度,那么该数字的最大尺寸可以是2 ^ 10。 任何大于这个的值和浮点数之间的距离大于0.5。

    如果你想得到+/- 0.0005(大约2 ^ -11)的精确度,数字可以是的最大尺寸是1.任何大于这个的数字,浮点数之间的距离大于0.0005。

  • 对于单精度 …

    如果您想要+/- 0.5(或2 ^ -1)的准确性,则该数字的最大大小为2 ^ 23。 任何大于这个的值和浮点数之间的距离大于0.5。

    如果你想得到一个+/- 0.0005(大约2 ^ -11)的精确度,那么这个数字的最大值就是2 ^ 13。 任何大于这个的值和浮点数之间的距离大于0.0005。

  • 对于双精度 …

    如果你想要一个+/- 0.5(或2 ^ -1)的准确性,那么该数字的最大尺寸是2 ^ 52。 任何大于这个的值和浮点数之间的距离大于0.5。

    如果你想得到+/- 0.0005(大约2 ^ -11)的精度,数字的最大尺寸是2 ^ 42。 任何大于这个的值和浮点数之间的距离大于0.0005。

对于浮点整数(我将以IEEE双精度给出我的答案),1和2 ^ 53之间的每个整数都是完全可表示的。 超过2 ^ 53,完全可表示的整数通过增加2的幂间隔开。 例如:

  • 2 ^ 53 + 2和2 ^ 54之间的每个第二整数都可以精确地表示。
  • 2 ^ 54 + 4和2 ^ 55之间的每4个整数都可以精确地表示。
  • 2 ^ 55 + 8和2 ^ 56之间的每个第8个整数都可以精确表示。
  • 2 ^ 56 + 16和2 ^ 57之间的每个第16个整数都可以精确地表示。
  • 2 ^ 57 +32和2 ^ 58之间的每个第32个整数都可以精确地表示。
  • 2 ^ 58 + 64和2 ^ 59之间的每个第64个整数可以精确地表示。
  • 2 ^ 59 + 128和2 ^ 60之间的每个第128个整数可以精确地表示。
  • 2 ^ 60 + 256和2 ^ 61之间的每256个整数都可以精确表示。
  • 2 ^ 61 + 512和2 ^ 62之间的每512个整数都可以精确表示。 。 。 。

不完全可表示的整数会四舍五入到最接近的可表示整数,所以最坏情况下舍入是可表示整数之间的间隔的1/2。

引用Peter R与MSDN的链接可能是一个很好的经验法则,但是现实情况当然更复杂。

“浮点”中的“点”是一个二进制小数点,而不是小数点这个事实,有一种击败我们直觉的方式。 经典的例子是0.1,它只需要一位十进制数的精度,但完全不能用二进制表示。

如果你有一个周末杀人,看看每个计算机科学家应该知道的浮点运算 。 您可能会特别感兴趣的部分精度和二进制到十进制转换 。

首先,IEEE-754-2008和-1985都没有16位浮点数; 但它是一个5位指数和10位小数的加法。 IEE-754使用专用符号位,所以正负范围是相同的。 另外,这个分数在前面有一个隐含的1,所以你得到一个额外的位。

如果你想精确到某个地方,就像你可以表示每个整数一样,答案相当简单:指数将小数点移到分数的右端。 所以,一个10比特的分数可以让你±2 11

如果你想在小数点后一位,你放弃一位,所以你有±2 10

单精度有一个23位的分数,所以你有±2 24整数。

你在小数点后需要多less精度,完全取决于你正在做的计算,以及你在做多less。

  • 2 10 = 1,024
  • 2 11 = 2,048
  • 2 23 = 8,388,608
  • 2 24 = 16777216
  • 2 53 = 9,007,199,254,740,992(双精度)
  • 2 113 = 10,384,593,717,069,655,257,060,992,658,440,192(四精度)

也可以看看

  • 双精度
  • 半精度

参见IEEE 754-1985 :

v =(-1)^ sign * s ^(exponent-exponent_bias)*(1 + fraction)

注意(1 +分数)。 正如@bendin所指出的那样,使用二进制浮点数,你不能expression简单的十进制值,如0.1。 这意味着你可以通过多次简单的加法来引入舍入错误或者调用诸如截断之类的东西。 如果你对任何精度感兴趣,唯一的方法是使用一个定点小数,它基本上是一个缩放整数。

如果我正确理解你的问题,这取决于你的语言。
对于C#,请查看MSDN参考 。 浮点数有7位精度和15-16位精度。

我花了相当长的一段时间才弄清楚,在Java中使用双打时,我的计算并没有失去显着的精度。 浮点实际上有很好的表示数字的能力,相当合理的精度。 我丢失的精度立即将用户键入的十进制数转换为原生支持的二进制浮点表示。 我最近开始把我所有的号码转换成BigDecimal。 BigDecimal在代码中的处理要比float或double更多,因为它不是原始types之一。 但另一方面,我将能够准确地表示用户input的数字。