【发布时间】:2017-09-20 13:23:55
【问题描述】:
我写了这行代码:
System.out.println(Math.pow(7, 23) % 143); // 7^23 mod 143
我预计输出为2,但输出为93.0。有人知道我在做什么错吗?
【问题讨论】:
-
不是溢出,而是
7^23不能精确表示为double。
我写了这行代码:
System.out.println(Math.pow(7, 23) % 143); // 7^23 mod 143
我预计输出为2,但输出为93.0。有人知道我在做什么错吗?
【问题讨论】:
7^23不能精确表示为double。
数字“溢出”double,这是 Math.pow() 期望和返回的。请改用BigInteger:
BigInteger.valueOf(7)
.pow(23)
.mod(BigInteger.valueOf(143))
或者像@Felk 所建议的那样一步一步:
BigInteger.valueOf(7)
.modPow(BigInteger.valueOf(23), BigInteger.valueOf(143))
【讨论】:
double 范围内,但无法以必要的精度表示。所以 BigInteger 解决方案是最直接的方法。
Math.pow的结果是double,有64位;其中 53 个是尾数位。这意味着任何大于2^53-1 = 9007199254740991 的整数都不能精确地表示为双精度数。
7^23 比 2^53-1 大(实际上只是比 2^64 大一点),所以不能精确表示。因此,% 的结果不是您所期望的。
改用BigInteger,正如@Costi 已经建议的那样。
【讨论】:
如果中间求幂结果太大而无法保存在变量中,请使用 Modular exponentiation algorithm。
System.out.println(powMod(7, 23, 143)); // = 2
// Example from Wikipedia with minor changes
private static int powMod(int base, int exponent, int modulus) {
if (modulus == 1)
return 0;
base %= modulus;
int result = 1;
while (exponent > 0) {
if ((exponent & 1) == 1)
result = (result * base) % modulus;
exponent >>= 1;
base = (base * base) % modulus;
}
return result;
}
【讨论】: