有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java数学。随机()与精度损失

以下内容未编译:

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。random()总是返回一个值小于1的双精度数,当与整数相加时,小数部分将由于精度损失而丢失。运行以下代码并查看意外结果:

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=42000000次迭代时,结果应该是42000000次。但事实并非如此!结果各不相同,即42000007对42000006对42000010等

为什么

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


共 (3) 个答案

  1. # 1 楼答案

    根据定义Math.random()返回从0.0到1.0的double结果。操作Math.random() + 1创建双结果,然后将其分配给int变量,从而生成整数结果。在每次迭代中,结果都是1,除非Math.random()正好返回1.0。这种情况发生的可能性很低,但仍然存在。从统计上看,这似乎是6000分之一。这就是某些循环迭代会在结果中添加2的原因

    所以,这里没有失去精确性。一切都是按规定进行的

  2. # 2 楼答案

    +=这样的赋值运算符执行隐式强制转换

    注:在这种情况下,Math.random()每次都将被舍入为0,这是一个严重的精度损失。;)

    然而Math.random() + 1被四舍五入为2的可能性非常小。e、 g.1.9999999将四舍五入为1,但1.9999999999999将四舍五入为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
    
  3. # 3 楼答案

    IEEE数学实现的细节指出了双精度/浮点到整数转换的精度损失和不可靠结果。例如,我曾经发现比较浮点数的代码:

    int x = 0;
    if (a <= b) 
    { 
        x = y; 
    }
    if (a > b) 
    { 
        x = z; 
    }
    

    有时结果是x == 0例如,if语句都没有捕捉到一个数字,我不得不将代码重写为:

    int x = 0; 
    if (a <= b) 
    { 
        x = y; 
    } 
    else 
    { 
         x = z; 
    }