浮点数的奇怪行为

我理解 random.Float() 带回一个介于 0.0 到 0.999 之间的浮点数...


但出于未知原因,几乎相同的代码会返回 2 个不同的答案。


我想了解为什么 t1 可以随机 1.0 而 t2 不能。


我试图检查一个类似的问题,但找不到任何类似的东西


    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);

        }

    }

没有错误消息我只是不明白为什么 t1 有时会带回 1.0 号而 t2 却没有。


编辑:t1 生成最大值 0.999... *0.1 即 0.0999... + 0.9 = 0.9999... t2 生成最大值 0.999... *0.9 即 0.8999... + 0.1 = 0.9999... 两者都应该是一样的不?


qq_遁去的一_1
浏览 107回答 1
1回答

慕村9548890

差异的主要原因是对于任何x < 1, .9 + x •.1 大于 .1 + x • .9,并且返回值小于 1。对于它返回的最大值,前一个表达式是这样的接近 1,将其四舍五入产生 1,但后一个表达式离 1 更远,将其四舍五入产生下一个低于 1 的表达式。Random.nextFloatfloatfloatfloat返回的最大值Random.nextFloat为Random.nextfloat16777215/16777216。让M成为这个最大值,让d = 1 − M = 1/16777216。如果我们t1用实数计算,它的最大值就是0.9 + M •.1。= .9 + (1− d )•.1 = 1− .1• d。类似地,t2将是 .1 + M •.9 = .1 + (1- d )•.9 = 1-.9• d。t1现在我们可以很容易地看到(如果用实数计算)的最大值与 1 相差 .1• d,但t2与 1 相差 .9• d。最大值Random.nextFloat返回 16777215/16777216 的一个原因是它是float小于 1 的最大值float。格式的精度是这样的,导致 1 的可表示值之间的步长是 1/16777216。这意味着该邻域中的两个可表示值是 16777215/16777216 和 1,d是它们之间的距离。我们上面的计算表明 的最大值与1 相差t1仅 .1• d。因此,当它四舍五入为 时float,1 是最接近的float。相反,最大值与 1 相差t2.9• d 。这意味着它与 16777215/16777216 仅相差 .1• d。所以,当它四舍五入时float,16777215/16777216 是最接近的float。那就是使用实数运算。下面,我将展示浮点运算。它有舍入误差,但事实证明这些误差很小,不会改变结果。在 中Java,源文本.1f和.9f被转换为float,产生 0.100000001490116119384765625 和 0.89999997615814208984375。使用 执行表达式中的算术运算double,然后将结果四舍五入float以赋值给t1或t2。t1可以计算出最大的:nextFloat代入yields的最大回报值0.9f + 16777215./16777216 * 0.1f;。算术计算double得出 0.999999971687793642871611154987476766109466552734375。转换为float1,因为该double值介于 0.999999940395355224609375(下一个较低的float值)和 1(下一个较高的值)之间,并且它更接近后者而不是前者。t2可以计算出最大的:nextFloat代入yields的最大回报值0.1f + 16777215./16777216 * 0.9f;。算术计算double得出 0.99999992400407933246242464520037174224853515625。转换为float收益率 0.999999940395355224609375。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java