我在 Java 中需要执行许多这样的大量操作:
int b = [big number];
int c = [big number];
int d = [big number];
long a = (long) (Math.pow(b, 4) * Math.pow(c, 2) * d);
我确信
a
不会超过long的大小。但是,Math.pow(b, 4)
或 Math.pow(c, 2)
可能会超过 int 的大小。我应该转换 Math.pow
的每个结果,还是 JVM 自己处理整个操作的转换?
我确信“a”不会超过long的大小。
这不是正确的边界值。
double
是 64 位值。基础信息学理论证明,因此 double 可以表示“最多”2“64”个唯一值。这很奇怪,因为 double 名义上表示它可以代表“任何数字”,并且存在超过 264 的数字。
因此,在实践中,double 可以表示一些(略小于 264)数字,任何其他值都会默默地舍入到最接近的“祝福”值。
举个简单的例子,0.1 不是这些值之一。因此为什么会这样:
double v = 0.0;
for (int i = 0; i < 10; i++) v += 0.1;
System.out.println(1.0 == v);
实际上打印错误。暗示双重数学表示 10 * 0.1 不知何故不是 1.0。这确实是它的工作原理。
考虑到这一点,双精度数可以准确地表示 2^53 以内的每个整数值。不是 long 可以表示的 2^64。因此,有些数字可以用 long 表示(例如 2^62-13),但 double 不能表示:
long x = (1L << 62) - 13;
System.out.println(x);
double v = x;
long y = (long) v;
System.out.println(y);
这些不打印相同的数字。
我必须投射到很长的距离吗?
是的。每次。原因是一个相当不令人满意的“因为规范是这么说的”。上面的解释在某种程度上解释了“为什么”规范是这样说的:作为程序员,您需要表明您承认这里的准确性存在限制;如果这些数字超过 2^52,则不太准确。您可以通过转换为 long 来表明这一点。