提问人:Renaud Marmion 提问时间:10/13/2023 最后编辑:Mark RotteveelRenaud Marmion 更新时间:10/14/2023 访问量:84
在乘法中使用 Math.pow 时,是否需要将每个操作数转换为 long?
Do I need to cast each operand to long when using Math.pow in a multiplication?
问:
我在 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);
我敢肯定,这不会超过一个长。但是,可能会或可能超过 int 的大小。 我应该强制转换 的每个结果,还是 JVM 会自行处理整个操作的强制转换?a
Math.pow(b, 4)
Math.pow(c, 2)
Math.pow
答:
我敢肯定,“a”不会超过长头的大小。
这不是正确的边框值。
double
是 64 位值。基础信息学理论证明,因此,一个双精度值最多可以表示 264 个唯一值。这很奇怪,因为 double 名义上说它可以代表“任何数字”,并且存在超过 264 个数字。
因此,在实践中,有一些(略小于 264)数字可以代表 double,任何其他值都会默默地四舍五入到最接近的这种“祝福”值。
举个简单的例子,0.1 不是这些值之一。因此,为什么会这样:
double v = 0.0;
for (int i = 0; i < 10; i++) v += 0.1;
System.out.println(1.0 == v);
实际上打印 false。建议双数学说 10 * 0.1 在某种程度上不是 1.0。这就是它的真正工作原理。
考虑到这一点,doubles 可以准确地表示每个整数值,最多 2^53。不是 2^64,这是多头可以代表的。因此,有些数字是多头可以表示的(例如 2^62-13),但双倍不能:
long x = (1L << 62) - 13;
System.out.println(x);
double v = x;
long y = (long) v;
System.out.println(y);
它们不会打印相同的数字。
我必须投射到多头吗?
是的。每次。
原因是一个相当不令人满意的“因为规范是这么说的”。上面的解释在某种程度上解释了为什么规范是这样说的:作为程序员,你需要表明你承认这里的准确性是有限的;如果这些数字超过 2^52,它就不太准确了。您可以通过转换为 long 来表示这一点。
评论
long
double
int
long
double
Math.pow()
Math.pow
仅存在 。通过使用,一切都变成了数学。您可以来回转换,但是,如果数字超过此值,则会导致舍入错误。double
Math.pow
double
2^52
"...我应该强制转换
Math.pow
的每个结果,还是 JVM 会自行处理整个操作的强制转换?..."
只需使用 pow 方法返回的 double 值即可。
它将保存一个 int 值。
double a = Math.pow(b, 4) * (Math.pow(c, 2) * d);
实际上,如果值预计会超过 64 位容器,则应使用 BigDecimal 或 BigInteger 类。
我推荐 String 构造函数方法。
BigInteger b = new BigInteger(""),
c = new BigInteger(""),
d = new BigInteger("");
BigInteger a = b.pow(4).multiply(c.pow(2).multiply(d));
评论
Math.pow(b, 4) * Math.pow(c, 2) * d
将在上下文中执行这些乘法,因为第一个乘法在 S 之间,并将在第二个乘法中转换为 A。这里不涉及。double
double
d
double
int
double
b
c
long
BigInteger