问题 Java Math.pow(a,b)时间复杂度


我想问下面代码的时间复杂度。是O(n)? (Math.pow()的时间复杂度是否为O(1)?)一般来说,Math.pow(a,b)是否具有时间复杂度O(b)或O(1)?提前致谢。

public void foo(int[] ar) {
   int n = ar.length;
   int sum = 0;
   for(int i = 0; i < n; ++i) {

     sum += Math.pow(10,ar[i]);

   }
}

2720
2017-09-05 23:53


起源

如果你只想要整数幂,那么编写自己的幂函数会更好。因为只有少数几个适合int的幂,所以只需使用查找表就可以了解O(1) - phuclv
@LưuVĩnhPhúc,但迭代地执行意味着你为^ b做b操作。不是吗?在原始问题中,如果数组长度为n,则数组的范围在0和n之间,最大值至少为n-1。因此上面的代码会有复杂性O(n ^ 2)不是吗? - seriously divergent
我在哪里说你为了权力而迭代地做什么?我说的是一个 查找表 喜欢 int pow10[] = {1, 10, 100, 1000,... 1000000000}; 得到 Math.pow(10, i) 简单地用 pow10[i]。即使您手动乘法,也只需要O(log n) 通过平方取幂 (实现基于整数的幂函数pow(int,int)的最有效方法),而不是O(n)喜欢迭代地做 - phuclv
哦,我明白你的意思了,谢谢! - seriously divergent


答案:


@Blindy谈到 可能 Java可以采用的方法 pow

首先,一般情况 不能 重复乘法。它不适用于指数不是整数的一般情况。 (签名 pow 是 Math.pow(double, double)!)

在OpenJDK 8代码库中,本机代码实现 pow 可以通过两种方式工作:

  • 第一次实施 e_pow.c 使用电源系列。该方法在C评论中描述如下:

    * Method:  Let x =  2   * (1+f)
    *      1. Compute and return log2(x) in two pieces:
    *              log2(x) = w1 + w2,
    *         where w1 has 53-24 = 29 bit trailing zeros.
    *      2. Perform y*log2(x) = n+y' by simulating multi-precision
    *         arithmetic, where |y'|<=0.5.
    *      3. Return x**y = 2**n*exp(y'*log2)
    
  • 第二个实现 w_pow.c 是一个包装 pow 标准C库提供的功能。包装器处理边缘情况。

现在,标准C库可能使用CPU特定的数学指令。如果确实如此,则选择JDK构建(或运行时)1 第二个实现,然后Java也会使用这些指令。

但无论哪种方式,我都看不到任何使用重复乘法的特殊情况代码的痕迹。你可以放心地认为它是 O(1)


1 - 我还没有深入研究何时可以进行选择。


7
2017-09-06 01:20



永远不必使用重复乘法。有一个 O(log N) 整数求幂算法。 - user207421
@EJP - 1)什么是“必要”,实际发生的事情不一样。 2)为 int 和 long,您可以使用特殊情况调整算法,以便 O(N) 比...更快 O(logN) 在范围内 N 和 X 你没有得到整数溢出的地方。 - Stephen C
@EJP例如将X == 0,1和2以及X <0视为特殊情况。如果使用shift处理X == 2的情况,则log3(2 ^ 32)<21;即X> = 3需要21轮或更少轮次的重复乘法。 - Stephen C


你可以考虑一下 Math.pow 是O(1)。

有一些可能的实现,从CPU汇编程序指令(Java不使用它)到稳定的软件实现,基于(例如)Taylor系列扩展的几个术语(虽然不完全是泰勒实现,还有一些更多具体算法)。

如果这是你担心的话,它肯定不会反复增加。


5
2017-09-06 00:04



为什么Java不使用汇编程序指令?实现是原生的。 - chrylis
没有人,包括C.硬件实现不完全符合标准(关于NaN处理IIRC)。您必须明确强制C编译器使用硬件指令(-ffastmath 例如gcc)。 - Blindy
@chrylis我所知道的计算机体系结构没有计算权力的指令。最简单的实现是 exp(b*log(a)) - phuclv