在乘法中使用 Math.pow 时,是否需要将每个操作数转换为 long?

问题描述 投票:0回答:1

我在 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 自己处理整个操作的转换?

java casting widening
1个回答
1
投票

我确信“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 来表明这一点。

© www.soinside.com 2019 - 2024. All rights reserved.