[英]Strange behavior of float point
I understand random.Float() bring back a float number between 0.0 to 0.999... 我了解random.Float()带回介于0.0到0.999之间的浮点数...
but for an unknown reason, almost the same code brings back 2 different answers. 但是由于未知的原因,几乎相同的代码会带回2个不同的答案。
I want to understand why t1 could random 1.0 and t2 can not. 我想了解为什么t1可以随机1.0,而t2不能随机。
I tried to check for a similar question but could not find out anything similar 我试图检查类似的问题,但找不到类似的问题
Random rand = new Random();
for (int i = 0; i < 1000000000; i++) {
float t1 = 0.9f + rand.nextFloat() * 0.1f;
float t2 = 0.1f + rand.nextFloat() * 0.9f;
if (t1 == 1.0f) {
System.out.println("t1 " + t1);
}
if (t2 == 1.0f) {
System.out.println("t2 " + t2);
}
}
no error messages I just can not understand why t1 bring back sometimes 1.0 number and t2 does not. 没有错误消息,我只是不明白为什么t1有时会带回1.0号而t2没有。
Edit: t1 generate maxmium of 0.999... *0.1 which is 0.0999... + 0.9 = 0.9999... t2 generate maxmimum of 0.999... *0.9 which is 0.8999... + 0.1 = 0.9999... Both should be the same no? 编辑:t1生成最大值为0.999 ... * 0.1,即0.0999 ... + 0.9 = 0.9999 ... t2生成最大值为0.999 ... * 0.9,即0.8999 ... + 0.1 = 0.9999 ...两者都应一样吗?
The primary cause of the difference is that .9 + x •.1 is larger than .1 + x • .9 for any x < 1, and Random.nextFloat
returns values less than 1. For the largest value it returns, the former expression is so close to 1 that rounding it to float
produces 1, but the latter expression is farther from 1, and rounding it to float
produces the next float
below 1. 造成这种差异的主要原因是,对于任何x <1,.9 + x •.1大于.1 + x •.9,并且
Random.nextFloat
返回的值小于1。对于返回的最大值,前者表达式非常接近1以至于将其四舍五入为float
会产生1,但后者的表达式离1更远,而将其四舍五入为float
会产生下一个小于1的float
。
The largest value that Random.nextFloat
returns is Random.nextfloat
16777215/16777216. Random.nextFloat
返回的Random.nextfloat
是Random.nextfloat
16777215/16777216。 Let M be this maximum, and let d = 1 − M = 1/16777216. 令M为该最大值,令d = 1 − M = 1/16777216。
If we calculated t1
using real numbers, its maximum value would be .9 + M •.1. 如果我们使用实数计算
t1
,则其最大值将为.9 + M •.1。 = .9 + (1− d )•.1 = 1−.1• d . = .9 +(1- d )•.1 = 1-.1• d 。 Similarly,
t2
would be .1 + M •.9 = .1 + (1- d )•.9 = 1-.9• d . 同样,
t2
将为.1 + M •.9 = .1 +(1- d )•.9 = 1-.9• d 。
Now we can easily see that the maximum of t1
(if calculated with real numbers) is .1• d away from 1, but t2
is .9• d away from 1. 现在,我们可以很容易地看到,最大的
t1
(如果与实数计算)为0.1•d远离1,但t2
有0.9•从1 天的路程。
A reason the largest value Random.nextFloat
returns is 16777215/16777216 is that it is the largest float
less than 1. The precision of the float
format is such that the steps between representable values leading up to 1 are 1/16777216. Random.nextFloat
返回的最大值是16777215/16777216的原因是它是小于1的最大float
。 float
格式的精度是导致可表示的值之间的步长为1/16777216。 This means that the two representable values in this neighborhood are 16777215/16777216 and 1, and d is the distance between them. 这意味着此邻域中的两个可表示值分别是16777215/16777216和1, d是它们之间的距离。 Our calculations above show us the maximum value of
t1
is just .1• d away from 1. So, when it is rounded to float
, 1 is the nearest float
. 上面的计算显示
t1
的最大值与t1
仅相差0.1• d 。因此,将其四舍五入为float
,1是最近的float
。
In contrast, the maximum value of t2
is .9• d away from 1. This means it is just .1• d away from 16777215/16777216. 相比之下,最大值
t2
有0.9•d离1。这意味着它仅仅是0.1•从一千六百七十七万七千二百十六分之一千六百七十七万七千二百十五ð路程。 So, when it is rounded to float
, 16777215/16777216 is the nearest float
. 因此,将其四舍五入为
float
,16777215/16777216是最近的float
。
That is using real-number arithmetic. 那就是使用实数算法。 Below, I will show the floating-point arithmetic.
下面,我将展示浮点算法。 It has rounding errors, but these turn out to be small enough not to change the results.
它具有舍入误差,但是事实证明这些误差足够小,不会改变结果。
In Java
, the source texts .1f
and .9f
are converted to float
, which yield 0.100000001490116119384765625 and 0.89999997615814208984375. 在
Java
,源文本.1f
和.9f
转换为float
,其结果为0.100000001490116119384765625和0.89999997615814208984375。 The arithmetic in the expressions is performed using double
, and then the result is rounded to float
for assignment to t1
or t2
. 表达式中的算术是使用
double
执行的,然后将结果舍入为float
以分配给t1
或t2
。
The largest that t1
can be may be calculated: 可以计算出
t1
的最大值:
nextFloat
yields 0.9f + 16777215./16777216 * 0.1f;
nextFloat
的最大返回值将产生0.9f + 16777215./16777216 * 0.1f;
. double
arithmetic yields 0.999999971687793642871611154987476766109466552734375. double
算术评估得出0.999999971687793642871611154987476766109109466552734375。 float
yields 1, because that double
value is between 0.999999940395355224609375 (the next lower float
value) and 1 (the next higher), and it is closer to the latter than to the former. float
产生1,因为该double
float
值介于0.999999940395355355224609375(下一个较低的float
值)和1(下一个较高的float
值)之间,并且比前者更接近后者。 The largest that t2
can be may be calculated: 可以计算出
t2
的最大值:
nextFloat
yields 0.1f + 16777215./16777216 * 0.9f;
nextFloat
返回值替换为0.1f + 16777215./16777216 * 0.9f;
. double
arithmetic yields 0.99999992400407933246242464520037174224853515625. double
算术评估得出0.99999992400407933246242464520037174224853515625。 float
yields 0.999999940395355224609375. float
产生0.999999940395355224609375。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.