Random 在0.0和1.0之间有多少个双精度数字?

Random 在0.0和1.0之间有多少个双精度数字?,random,floating-point,double,precision,Random,Floating Point,Double,Precision,这件事我已经想了很多年了,但我以前从未花时间问过 许多(伪)随机数生成器生成一个介于0.0和1.0之间的随机数。从数学上讲,这个范围内有无穷多个数字,但是double是一个浮点数,因此具有有限的精度 因此,问题是: 在0.0和1.0之间有多少个double数字 1和2之间的数字是否也一样多?100到101之间?在10^100和10^100+1之间 注意:如果有区别的话,我对Java的double的定义特别感兴趣 2^53-包含隐藏位的64位浮点数的有效位/尾数的大小 大致是的,因为sifnifi

这件事我已经想了很多年了,但我以前从未花时间问过

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

因此,问题是:

  • 在0.0和1.0之间有多少个
    double
    数字
  • 1和2之间的数字是否也一样多?100到101之间?在10^100和10^100+1之间
  • 注意:如果有区别的话,我对Java的
    double
    的定义特别感兴趣

  • 2^53-包含隐藏位的64位浮点数的有效位/尾数的大小
  • 大致是的,因为sifnificand是固定的,但指数是变化的
  • 有关更多信息,请参阅。

    IBM的文章提供了以下代码片段来解决此问题(在浮动中,但我怀疑它也适用于双精度):

    公共类浮动计数器{
    公共静态void main(字符串[]args){
    浮动x=1.0F;
    int numFloats=0;
    
    虽然(xJava
    double
    s为格式,因此它们有52位分数;在两个相邻的二次幂(包括一次幂,不包括下一次幂)之间,因此将有2到52次幂不同的
    double
    s(即其中4503599627370496次)。例如,这是包含0.5和排除1.0之间的不同
    double
    s的数量,确切地说,许多也位于包含1.0和排除2.0之间,以此类推

    计算0.0到1.0之间的
    双倍
    比计算2的幂更困难,因为该范围包含许多2的幂,而且,还涉及到非规范化数字的棘手问题。11位指数中有10位涵盖了所讨论的范围,因此,包括非规范化数字(我认为有几种
    NaN
    )你会有1024倍的
    二次幂之间的
    double
    s——总之不超过
    2**62
    。除去非规范化的&c,我相信计数是1023倍
    2**52

    对于像“100到100.1”这样的任意范围,它甚至更难,因为上界不能精确地表示为
    double
    (不是任何二次幂的精确倍数).作为一个方便的近似值,由于二次幂之间的级数是线性的,你可以说所述范围是二次幂(64和128)之间跨度的
    0.1/64
    th,因此你预计

    (0.1 / 64) * 2**52
    

    不同的
    double
    s——这是指
    7036874417766.4004
    …给出或获取一个或两个;-)。

    Java double是一个IEEE 754二进制64号

    这意味着我们需要考虑:

  • 尾数是52位
  • 指数是带有1023偏差的11位数字(即添加1023)
  • 如果指数均为0,尾数不为零,则称该数字为非标准化数
  • 这基本上意味着总共有2^62-2^52+1个可能的双精度表示,根据标准,这些双精度表示介于0和1之间。请注意,2^52+1用于删除非标准化数字的情况

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


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

    每一个
    值的表示法n介于
    0x000000000000
    0x3ff0000000000000
    之间,位于区间[0.0,1.0]内。这是(2^62-2^52)个不同的值(加或减一对,取决于是否计算端点)

    区间[1.0,2.0]对应于
    0x3ff0000000000000
    0x400000000000000
    之间的表示,即2^52个不同的值

    区间[100.0,101.0]对应于
    0x405900000000000
    0x4059400000000000
    之间的表示,即2^46个不同的值

    在10^100和10^100+1之间没有双精度。这两个数字都不能用双精度表示,也没有介于两者之间的双精度数字。最接近的两个双精度数字是:

    99999999999999982163600188718701095...
    


    其他人已经解释过,在[0.0,1.0]范围内大约有2^62个翻倍 (这并不奇怪:几乎有2^64个不同的有限双精度;其中一半为正,大约一半小于1.0。)


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

    是的,但这是用于
    浮点
    ,而不是
    双精度
    -
    浮点
    s的分数值为23位,因此
    2**23->8388608
    两个相邻幂之间的值不同(当然,“包含”部分意味着您必须再计算一个,下一个二的幂)(
    double
    s有52位分数!@Alex:我想我必须让程序(修改为double)运行到宇宙末日左右,然后才能得到结果…:(我觉得很傻;我只是写了
    double
    等价物,并想“嘿,我会在大约5分钟内回答我自己的问题…”p
    99999999999999982163600188718701095...
    
    10000000000000000159028911097599180...