java - Math.random() 和精度损失的好奇心

标签 java math

以下不编译:

int result = Math.random() + 1;

error: possible loss of precision
    int result = Math.random() + 1;
                               ^
    required: int
    found:    double

但以下确实编译:

int result = 0;
result += Math.random() + 1;

为什么?

将可编译代码放入嵌套循环中,人们会期望结果在每次迭代中递增 1,因为 Math.random() 总是返回一个值小于 1 的 double 值,并且当与整数相加时,小数部分将是由于精度损失而丢失。运行以下代码并看到意想不到的结果:

public class MathRandomCuriosity
{
  public static void main(String[] args)
  {
    int result = 0;
    for (int i = 0; i < 10; i++)
    {
      // System.out.println(result);
      for (int j = 0; j < 20; j++)
      {
        // System.out.println(result);
        for (int k = 0; k < 300; k++)
        {
          // System.out.println(result);
          for (int m = 0; m < 7000; m++)
          {
            result += Math.random() + 1;
          }
        }
      }
    }
    System.out.println(result);
  }
}

对于 10*20*300*7000 = 42,000,000 次迭代,结果应为 42,000,000。但事实并非如此!结果各不相同,即 42,000,007 与 42,000,006 与 42,000,010 等。

为什么?

顺便说一下...这不是任何地方都在使用的代码,它来 self 在时事通讯中收到的一个测验。嵌套循环的原因是我可以每隔一段时间查看结果的值。

最佳答案

+= 等赋值运算符会进行隐式转换。

注意:在这种情况下,Math.random() 每次都会向下舍入为 0,这会严重降低精度。 ;)

但是 Math.random() + 1 有很小的机会四舍五入为 2。例如1.999999 将四舍五入为 1,但 1.9999999999999999 将四舍五入为 2(但 double + 运算符而不是转换为 int)。

long l = Double.doubleToLongBits(1.0);
double d0_999etc = Double.longBitsToDouble(l -1);
System.out.println("The value before 1 is " +d0_999etc+" cast to (int) is "+ (int) d0_999etc);
System.out.println("The value before 1, plus 1 is " +(1+d0_999etc)+" cast to (int) is "+(int)(1 +d0_999etc));

打印

The value before 1 is 0.9999999999999999 cast to (int) is 0
The value before 1, plus 1 is 2.0 cast to (int) is 2

关于java - Math.random() 和精度损失的好奇心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8402500/

相关文章:

java - Ant build.xml 中的 Cobertura “unable to locate file”

java - 在内存中存储等距网格的最佳方法是什么?

java - 如何在 ANTLR 3 树解析器中表达多个节点

math - 检查三个圆是否适合一个三角形

algorithm - Tower Breakers - 带有除数的 nim 游戏变体

java - 使用类型继承的数字组层次结构

java - 如何在 while 循环中安全地扫描整数?

java - java中将JSON数据结构遍历成树

c++ - 舍入误差减少?

c++ - 用 Lapack 的 dgeqrf_ 求解线性系统