我对浮点数的表示方式略知一二,但恐怕还不够。
一般的问题是:
对于给定的精度(为了我的目的,精确的十进制小数位数) ,16位、32位和64位 IEEE-754系统可以表示什么范围的数字?
具体来说,我只对精确到 +/-0.5(一个位)或 +/-0.0005(千分之一位)的16位和32位数字的范围感兴趣。
如果我没有理解错你的问题,那就要看你的语言了。 对于 C # ,查看 MSDN 参考文献。 Float 有7位精度和双15-16位精度。
首先,IEEE-754-2008和 -1985都没有16位浮点数; 但是它是一个提议的添加,具有5位指数和10位分数。IEE-754使用专用的符号位,所以正负范围是相同的。此外,分数前面有一个隐含的1,所以你得到一个额外的位。
如果您希望精确到某个位置,比如您可以表示每个整数,那么答案相当简单: 指数将小数点移动到小数部分的右端。所以,一个10位的分数可以得到 ± 211。
如果你想要小数点后面的一位,你就要放弃小数点前面的一位,所以你得到 ± 210。
单精度有一个23位的分数,所以有 ± 224整数。
在小数点后需要多少位的精度完全取决于您正在进行的计算,以及您正在进行的计算数量。
从 Peter R 链接到 MSDN 参考文献的精确引用可能是一个很好的经验法则,但是实际情况当然更加复杂。
事实上,“浮点数”中的“点”是一个 二进制点,而不是小数点,有一种方法可以打败我们的直觉。经典的例子是0.1,它只需要一个十进制数字的精度,但是完全不能用二进制表示。
如果你有一个周末要打发,看看 计算机科学家应该知道的浮点数算法。您可能对 精确和 二进制到十进制转换的章节特别感兴趣。
对于给定的 IEEE-754浮点数 X,如果
2^E <= abs(X) < 2^(E+1)
那么从 X到下一个最大可表示浮点数(Epsilon)的距离是:
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。任何大于此限制的 X 导致浮点数之间的距离大于0.5。
如果希望精度为 +/-0.0005(大约2 ^ -11) ,则该数字的最大大小为1。任何大于此最大限制的 X 导致浮点数之间的距离大于0.0005。
对于 单精度..。
如果希望精度为 +/-0.5(或2 ^-1) ,则该数字的最大大小为2 ^ 23。任何大于此限制的 X 导致浮点数之间的距离大于0.5。
如果希望精度为 +/-0.0005(大约2 ^ -11) ,则该数字的最大大小为2 ^ 13。任何大于此限制的 X 导致浮点数之间的距离大于0.0005。
对于 双精度..。
如果希望精度为 +/-0.5(或2 ^-1) ,则该数字的最大大小为2 ^ 52。任何大于此限制的 X 导致浮点数之间的距离大于0.5。
如果希望精度为 +/-0.0005(大约2 ^ -11) ,则该数字的最大大小为2 ^ 42。任何大于此限制的 X 导致浮点数之间的距离大于0.0005。
见 IEEE 754-1985:
注(1 + 分数)。正如 @ bendin指出的,使用二进制浮点数,不能表示简单的十进制值,如0.1。这意味着您可以通过多次执行简单的加法或调用截断之类的操作来引入舍入错误。如果您对任何类型的精度感兴趣,那么实现它的唯一方法是使用定点小数,它基本上是一个缩放整数。
我花了很长时间才弄明白,当在 Java 中使用双精度时,我并没有在计算中失去显著的精度。浮点数实际上有一个非常好的能力,以相当合理的精度表示数字。当我将用户输入的 十进制数字转换为本机支持的 二进制浮点表示时,我立即失去了精度。我最近开始把我所有的数字转换成 BigDecimal。BigDecimal 在代码中要比 float 或 double 处理的工作量大得多,因为它不是基元类型之一。但另一方面,我将能够准确地表示用户输入的数字。
对于浮点整数(我将用 IEEE 双精度来给出我的答案) ,1到2 ^ 53之间的每个整数都是精确可表示的。超过2 ^ 53,精确可表示的整数被两个幂的递增所分隔。例如:
不完全可表示的整数四舍五入到最接近的可表示整数,所以最坏的情况四舍五入是可表示整数间距的1/2。