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等
为什么
顺便说一下。。。这不是任何地方都在使用的代码,它来自我在时事通讯中收到的一个测验。嵌套循环的原因是,我可以每隔一段时间查看结果的值
# 1 楼答案
根据定义
Math.random()
返回从0.0到1.0的double
结果。操作Math.random() + 1
创建双结果,然后将其分配给int变量,从而生成整数结果。在每次迭代中,结果都是1,除非Math.random()
正好返回1.0。这种情况发生的可能性很低,但仍然存在。从统计上看,这似乎是6000分之一。这就是某些循环迭代会在结果中添加2的原因所以,这里没有失去精确性。一切都是按规定进行的
# 2 楼答案
像
+=
这样的赋值运算符执行隐式强制转换注:在这种情况下,
Math.random()
每次都将被舍入为0,这是一个严重的精度损失。;)然而
Math.random() + 1
被四舍五入为2的可能性非常小。e、 g.1.9999999将四舍五入为1,但1.9999999999999将四舍五入为2(但double +
运算符而不是强制转换为int
)印刷品
# 3 楼答案
IEEE数学实现的细节指出了双精度/浮点到整数转换的精度损失和不可靠结果。例如,我曾经发现比较浮点数的代码:
有时结果是
x == 0
例如,if语句都没有捕捉到一个数字,我不得不将代码重写为: