Java Math.pow的错误结果

Max*_*ers 12 java math pow long-integer

如果您尝试运行以下代码

public class Main {
   public static void main(String[] args) {
       long a = (long)Math.pow(13, 15);
       System.out.println(a + " " + a%13);
   }
}
Run Code Online (Sandbox Code Playgroud)

你会得到"51185893014090752 8"

的正确值13 ^ 1551185893014090757,即,比由返回的结果更大的Math.pow5.任何可能导致它的想法?

aro*_*oth 10

您已经超过了双精度浮点值中可用的有效位数(~15到16).一旦你这样做,你不能指望你的结果中最不重要的数字实际上是有意义的/精确的.

如果您需要在Java中进行任意精确的算术运算,请考虑使用BigIntegerBigDecimal.


Jon*_*eet 6

问题是当你得到更高和更高的double值时,连续值之间的差距会增加 - double不能代表其范围内的每个整数值,这就是这里出了问题.它将最接近的 double值返回到确切的结果.

  • 我认为你的意思是粒度(粗糙度)会增加? (2认同)

Pie*_*gel 5

这不是精确度问题.Math.pow方法执行结果的近似.要获得正确的结果,请使用以下代码.

long b = 13;
for(int i = 0; i != 14; i ++) {
    b = b * 13;
}
System.out.println(b);
Run Code Online (Sandbox Code Playgroud)

输出是预期结果51185893014090757L.

更一般地,当指数是整数时,应避免使用Math.pow方法.首先,结果是近似值,其次是计算成本更高.

Math.pow(以及Math类中的大多数其他方法)的实现基于网络库netlib作为"Freely Distributable Math Library"包(请参阅StrictMath javadoc).可以在e_pow.c上找到C中的实现.


Nee*_*eet 1

double 的精度有限,尾数为 52 位,大约等于 15 到 16 位小数。因此,您尝试计算的数字不能再用双精度数来表示(精确地)。