我正在试验我在这里找到的Java专家通讯中的代码.
public class MeaningOfLife {
public static String findOutWhatLifeIsAllAbout() {
int meaning = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 20; j++) {
for (int k = 0; k < 300; k++) {
for (int m = 0; m < 7000; m++) {
meaning += Math.random() + 1;
}
}
}
}
return String.valueOf(meaning).replaceAll("0*$", "");
}
public static void main(String[] args) {
System.out.println(findOutWhatLifeIsAllAbout());
}
}
Run Code Online (Sandbox Code Playgroud)
一旦我意识到存在使用复合赋值运算符 + = 的隐式转换,问题"它打印什么"的答案似乎很明显.
但它打印的内容如下:420000006或420000007,而不是(预期的)420000000(或"42",删除尾随零后).
所以这表明从double转换为int并不总是只删除double中的小数部分,如下所示:如何在Java中将double转换为int?
所以我做了一些试验,这是我发现的一个例子:
System.out.println((int) (131070.99999999999)); // -> 131070
System.out.println((int) (131071.99999999999)); // -> 131071
System.out.println((int) (131072.99999999999)); // -> 131073 !!!
System.out.println((int) (131073.99999999999)); // -> 131074 !!!
System.out.println((int) (16382.999999999999)); // -> 16382
System.out.println((int) (16383.999999999999)); // -> 16383
System.out.println((int) (16384.999999999999)); // -> 16385 !!!
System.out.println((int) (16385.999999999999)); // -> 16386 !!!
Run Code Online (Sandbox Code Playgroud)
...所以现在我正在寻找这种行为的解释???
许多十进制值不可能是双值.在使用它们之前,首先必须将它们挤压到最接近的双值.
示例:16384.999999999999没有精确的双重表示.两个最接近的值是16384.99999999999636202119290828704833984375和16385.0.压缩导致差异大约0.000000000003,而挤压导致差异0.000000000001- 上升导致更接近的值,所以这就是它的解释.
也许你会对这个事实感到惊讶
System.out.println(131072.99999999999); // -> 131073 !!!
Run Code Online (Sandbox Code Playgroud)
你没有把事件转换成int.
在Java(以及其他语言)中存在双重表示的问题.系统不像人类那样使用"十进制"部分.
这里详细解释:http: //en.wikipedia.org/wiki/Floating_point
但是,简而言之,双重值是存储为最终结果的几个部分(图像类似于-1.23*10 ^ -15).而且每个给定的数字只有有限的空间.因此,最终您无法准确表示Double.MAX_VALUE和Double.MIN_VALUE之间的每个数字.
您可以根据需要编写包含任意double数字的文字,但这并不意味着double值可以表示您编写的文字.
摆脱int演员,以更仔细地看到double你的文字的表现形式将在它被铸造之前int:
System.out.println(16383.999999999999);
System.out.println(16383.999868686868686999999999);
System.out.println(16384.999999999999);
System.out.println(16385.999999999999);
Run Code Online (Sandbox Code Playgroud)
输出:
16383.999999999998
16383.99986868687
16385.0
16386.0
Run Code Online (Sandbox Code Playgroud)
将这些转换为int,你会看到:
16383
16383
16385
16386
Run Code Online (Sandbox Code Playgroud)