为了账号安全,请及时绑定邮箱和手机立即绑定

浮点数的奇怪行为

浮点数的奇怪行为

qq_遁去的一_1 2023-04-26 14:20:05
我理解 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... 两者都应该是一样的不?
查看完整描述

1 回答

?
慕村9548890

TA贡献1884条经验 获得超4个赞

差异的主要原因是对于任何x < 1, .9 + x •.1 大于 .1 + x • .9,并且返回值小于 1。对于它返回的最大值,前一个表达式是这样的接近 1,将其四舍五入产生 1,但后一个表达式离 1 更远,将其四舍五入产生下一个低于 1 的表达式。Random.nextFloatfloatfloatfloat

返回的最大值Random.nextFloatRandom.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以赋值给t1t2

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。


查看完整回答
反对 回复 2023-04-26
  • 1 回答
  • 0 关注
  • 106 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信