Random 在0.0和1.0之间有多少个双精度数字?
这件事我已经想了很多年了,但我以前从未花时间问过 许多(伪)随机数生成器生成一个介于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
double
是一个浮点数,因此具有有限的精度
因此,问题是:
double
数字double
的定义特别感兴趣
公共类浮动计数器{
公共静态void main(字符串[]args){
浮动x=1.0F;
int numFloats=0;
虽然(xJavadouble
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...