0.0到1.0之间有多少个双数?

时间:2010-06-05 02:51:23

标签: random floating-point double precision

这是我多年来一直想到的事情,但我从来没有花时间问过。

许多(伪)随机数生成器生成介于0.0和1.0之间的随机数。在数学上,此范围内存在无限数,但double是浮点数,因此具有有限的精度。

所以问题是:

  1. 0.0到1.0之间有多少double个数字?
  2. 1到2之间的数字是否一样多? 100到101之间?介于10 ^ 100和10 ^ 100 + 1?
  3. 之间

    注意:如果它有所不同,我特别感兴趣的是Java对double的定义。

6 个答案:

答案 0 :(得分:64)

Java double采用IEEE-754格式,因此它们具有52位分数;在任何两个相邻的2的幂之间(包括一个并且不包括下一个),因此将存在2到52次幂不同的double s(即,其中的4503599627370496)。例如,这是包括在0.5和1.0之间的不同double的数量,并且恰好许多也包括在1.0和2.0之间,等等。

在0.0和1.0之间计算doubles比在2的幂之间计算要困难,因为在该范围内包含许多2的幂,并且还有一个涉及非规范化数字的棘手问题。指数的11位中的10位覆盖了所讨论的范围,因此,包括非规范化数字(我认为有几种NaN),你有double次的1024次幂两个 - 总共不超过2**62。不包括非规范化& c,我相信计数将是2**52的1023倍。

对于像“100到100.1”这样的任意范围,它甚至更难,因为上限不能精确地表示为double(不是两个幂的精确倍数)。作为一个方便的近似,由于2的幂之间的进展是线性的,你可以说所述范围是2(64和128)的周围幂之间的跨度的0.1 / 64,所以你期望< / p>

(0.1 / 64) * 2**52

distinct double s - 来7036874417766.4004 ...给或拿一两个; - )。

答案 1 :(得分:39)

表示在double0x0000000000000000之间的每个0x3ff0000000000000值位于区间[0.0,1.0]中。那是(2 ^ 62 - 2 ^ 52)个不同的值(加上或减去一对,取决于你是否计算端点)。

区间[1.0,2.0]对应于0x3ff00000000000000x400000000000000之间的表示;这是2 ^ 52个不同的值。

区间[100.0,101.0]对应于0x40590000000000000x4059400000000000之间的表示;这是2 ^ 46个不同的值。

10 ^ 100和10 ^ 100 + 1 之间没有双打。这些数字中的任何一个都不能以双精度表示,并且它们之间没有双精度数。最接近的两个双精度数是:

99999999999999982163600188718701095...

10000000000000000159028911097599180...

答案 2 :(得分:6)

其他人已经解释过在[0.0,1.0]范围内有大约2 ^ 62个双打 (并不奇怪:有近2 ^ 64个不同的有限双打;其中一半是正数,而那些的大约一半都是<1.0。)

但是你提到了随机数生成器:请注意,生成0.0到1.0之间的数字的随机数生成器通常不会生成所有这些数字;通常它只产生n / 2 ^ 53形式的数字,其中n为整数(参见例如nextDouble的Java文档)。因此,random()输出通常只有大约2 ^ 53(+/- 1,具体取决于包含哪些端点)的可能值。这意味着永远不会生成[0.0,1.0]中的大多数双打。

答案 3 :(得分:3)

来自IBM的文章Java's new math, Part 2: Floating-point numbers提供了以下代码片段来解决这个问题(在浮点数中,但我怀疑它也适用于双打):

public class FloatCounter {

    public static void main(String[] args) {
        float x = 1.0F;
        int numFloats = 0;
        while (x <= 2.0) {
            numFloats++;
            System.out.println(x);
            x = Math.nextUp(x);
        }
        System.out.println(numFloats);
    }
}

他们对此发表了评论:

  

事实证明,正好有8,388,609个浮点数介于1.0和2.0之间;很大但很难在这个范围内存在无数的实数无穷大。连续数字相差约0.0000001。该距离在最后一个位置称为ULP,用于最小精度或单位的单位。

答案 4 :(得分:2)

  1. 2 ^ 53 - 包含隐藏位的64位浮点数的有效数字/尾数的大小。
  2. 大致是的,因为sifnificand是固定的,但是指数会改变。
  3. 有关详细信息,请参阅wikipedia article

答案 5 :(得分:1)

Java double是IEEE 754二进制64号。

这意味着我们需要考虑:

  1. 尾数是52位
  2. 指数是11位数,1023偏差(即加上1023)
  3. 如果指数全为0且尾数不为零,那么该数字被称为非标准化
  4. 这基本上意味着总共有2 ^ 62-2 ^ 52 + 1个可能的双重表示,根据标准在0和1之间。注意2 ^ 52 + 1是去除案例的非标准化数字。

    请记住,如果尾数为正,但指数为负数,则为正数但小于1: - )

    对于其他数字,它有点难,因为边缘整数在IEEE 754表示中可能无法以精确的方式表示,并且因为指数中使用的其他位能够表示数字,所以越大数字越低,不同的值。