Answers:
Java double
采用IEEE-754格式,因此它们有52位的分数;因此,在任意两个相邻的2的幂之间(包括一个double
且不包括下一个),将有2到52的幂不同(即其中的4503599627370496)。例如,这是double
包含0.5到排除1.0之间的distance s 的数量,也恰好有很多位于包含1.0到排除2.0之间的distance s,依此类推。
doubles
在0.0和1.0之间进行计数比在2的幂之间进行计数更困难,因为该范围内包含2的很多幂,而且,一个也进入了非正规数的棘手问题。指数的11位中有10位涵盖了所讨论的范围,因此,包括非规格化的数字(我认为是几种NaN
),您的double
s的幂是1024 的2的幂次之和- 2**62
总数之和。不包括非规范化的&c,我相信这个数字将是1023次2**52
。
对于“ 100到100.1”之类的任意范围,这甚至更加困难,因为上限不能精确地表示为a double
(不是2的幂的精确倍数)。作为一个方便的近似值,由于2的幂之间的线性关系是线性的,因此您可以说该范围是0.1 / 64
2的幂(64和128)之间的跨度的th,因此您可以期望
(0.1 / 64) * 2**52
与众不同的double
s-得出7036874417766.4004
...或给出一或两个;-)。
2**64
double值(因为它是64位类型),而且显然这些值中有很大一部分位于它们之间0..1
?
每个double
表示形式介于之间0x0000000000000000
并0x3ff0000000000000
位于[0.0,1.0]之间的值。那是(2 ^ 62-2 ^ 52)个不同的值(加上或减去一对,取决于您是否计算端点)。
间隔[1.0,2.0]对应于0x3ff0000000000000
和之间的表示形式0x400000000000000
。那是2 ^ 52个不同的值。
间隔[100.0,101.0]对应于0x4059000000000000
和之间的表示形式0x4059400000000000
;那是2 ^ 46个不同的值。
在10 ^ 100和10 ^ 100 +1之间没有双打。这些数字中的任何一个都不能用双精度来表示,并且它们之间没有双精度。最接近的两个双精度数字是:
99999999999999982163600188718701095...
和
10000000000000000159028911097599180...
其他人已经解释说,在[0.0,1.0]范围内大约有2 ^ 62的两倍。
(不是真的令人吃惊:有近2 ^ 64个不同有限双打;其中一半是正的,和大约一半的那些是<1.0。)
但是您提到了随机数生成器:请注意,生成0.0到1.0之间的数字的随机数生成器通常不能生成所有这些数字。通常,它只会产生n / 2 ^ 53形式的数字,其中n为整数(例如,参见Java文档nextDouble)。因此,通常只有大约2 ^ 53(+/- 1,取决于所包括的端点)可能的random()
输出值。这意味着将永远不会生成[0.0,1.0]中的大多数双打。
Java的新数学文章,第2部分: IBM的浮点数提供了以下代码片段来解决此问题(以float形式,但我怀疑它也可以用于double形式):
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);
}
}
他们对此有以下评论:
事实证明,在1.0和2.0(含)之间,总共有8,388,609个浮点数;很大,但几乎没有存在于此范围内的实数的无穷大。连续的数字大约相隔0.0000001。此距离称为最低精度单位的ULP或最后一个单位。
float
,不是 double
- float
■找23位的价值部分,所以2**23 -> 8388608
两个相邻的大国之间的不同的值(当然,‘包容性’的部分意思是你要算一个,两个下一功率)。 double
s有52位分数!
double
等价的文章,并以为“嘿,我会在大约5分钟内回答我自己的问题……”
double
的两个相邻的大国之间将需要约52天(println
当然是非常不可能跑那么快,不管是什么,所以让我们假设一个陈述消失了;-)。我认为在功能强大但实际的机器上花费一年或更短的时间是可行的;-)。
有关更多信息,请参见Wikipedia文章。
1
是错误的,因为隐藏位始终是一个-因此2^52
,没有 2^53
明显的值(两个相邻的大国,一个包括和下一个排除之间- 不!0.0和1.0之间)。
Java double是IEEE 754 binary64数字。
这意味着我们需要考虑:
这基本上意味着总共有2 ^ 62-2 ^ 52 + 1个可能的双重表示形式,根据标准,这些表示形式介于0和1之间。请注意,2 ^ 52 + 1是要去除未归一化的情况数字。
请记住,如果尾数为正,但指数为负,则数为正,但小于1 :-)
对于其他数字,这有点困难,因为边缘整数可能无法以IEEE 754表示形式精确地表示,并且因为指数中还使用其他位来表示数字,所以数字越大表示数字越小不同的值。