鉴于下面的枚举,
enum SizeUnits {
Bytes(1),
Kilobytes(1024),
Megabytes(1024 * 1024),
Gigabytes(1024 * 1024 * 1024),
Terabytes(1024 * 1024 * 1024 * 1024),
Petabytes(1024 * 1024 * 1024 * 1024 * 1024);
private final long multiplier;
private SizeUnits(long mult) {
this.multiplier = mult;
System.out.println("mult="+mult);
}
}
我得到以下输出:
mult=1
mult=1024
mult=1048576
mult=1073741824
mult=0
mult=0
显然,最后两个是内部剪裁,我不明白为什么。考虑到我使用long
而claimed max value for long with Java 8是:,它看起来应该不应该是这样的:
2^64-1
。
如果它是以整数的大小剪裁,我本来期望它也剪辑1073741824。此外,它不仅仅是环绕,而是实际将值剪切为零。
为什么它将最后两个条目剪辑为零?
阿。文字的类型。当然。
注意(如下面的答案所述)如果我将L
作为该行的最后一个条目,它仍然会溢出更大的情况,因为显然它没有将操作提升为{{ 1}}在溢出之前。
现在,当尝试通过
进行投射时,为什么它不起作用是有道理的long
但这有效:
(long)(1024 * 1024 * 1024 * 1024 * 1024)
它是什么时候溢出的问题。谢谢大家!
答案 0 :(得分:7)
最后两次溢出。它们等于2^40
和2^50
哪个不适合int。这些是整数,而不是长
将L
添加到1024
值中的第一个:
Terrabytes(1024L * 1024 * 1024 * 1024)
当你添加L
时,你明确表示它很长。
然后其他操作数也被提升为长,
结果不会溢出。
另请尝试:
1)long x = 1024 * 1024 * 1024 * 1024 * 1024;
2)long y = 1024L * 1024 * 1024 * 1024 * 1024;
查看您在x
和y
中获得的值。
答案 1 :(得分:2)
你所谓的“剪辑”是数字溢出。你反复乘以(int
)2的幂,直到它们溢出。因为只保留低32位,所以得到0
因为唯一要设置的位超出了低位32位。
如果您有千兆字节值(1024 * 1024 * 1024),则int
已经是2 ^ 30:
01000000 00000000 00000000 00000000
当乘以另一个1024时,如果精度允许,你会得到这个:
1 00000000 00000000 00000000 00000000 00000000
但只保留低位32位,即0
。
您可以将第一个1024
投射到long
或使用long
字面值。 (它必须是第一个文字,以确保long
算术整个过程并避免中间溢出。)
(long) 1024 * 1024 * 1024 * 1024
1024L * 1024 * 1024 * 1024
long
有64位,足以满足您的需要(2 50 )。但是,如果你继续前进,你需要大于Long.MAX_VALUE
,2 63 -1的值,那么切换到使用BigInteger
s。
答案 2 :(得分:1)
您只是将计算结果转换为long。 2 ^ 32的任何倍数都将溢出为0.
另一种写作方式是
enum SizeUnits {
Bytes(1L << 0),
Kilobytes(1L << 10),
Megabytes(1L << 20),
Gigabytes(1L << 30),
Terrabytes(1L << 40),
Petabytes(1L << 50),
Exabytes(1L << 60);
private final long multiplier;
private SizeUnits(long mult) {
this.multiplier = mult;
System.out.println(name() + ": mult=" + mult);
}
}