快速功能类似于^ b

时间:2012-09-22 06:38:12

标签: java performance function pow

这有点模糊,但我需要一个可以非常快速地计算的函数,类似于^ b,其中a介于0和1之间,b非常大。对于许多b,它将一次计算一个a。理想情况下,结果将在0.4%以内。提前谢谢。

3 个答案:

答案 0 :(得分:2)

将我的评论转化为答案:

既然你提到b大到足以舍入为整数,那么一种方法就是通过平方来使用Binary Exponentiation algorithm

Math.pow()很慢,因为它需要处理非整数幂。因此,可以在您的情况下做得更好,因为您可以使用整数供电算法。


与往常一样,对您的实施进行基准测试,看它是否真的比Math.pow()更快。


这是OP找到的实现:

public static double pow(double a, int b) {
    double result = 1;
    while(b > 0) {
        if (b % 2 != 0) {
            result *= a;
            b--;
        } 
        a *= a;
        b /= 2;
    }

    return result;

}

这是我快速而肮脏(未经优化)的实施:

public static double intPow(double base,int pow){
    int c = Integer.numberOfLeadingZeros(pow);

    pow <<= c;

    double value = 1;
    for (; c < 32; c++){
        value *= value;
        if (pow < 0)
            value *= base;
        pow <<= 1;
    }

    return value;
}

这适用于所有积极的pow。但我没有对Math.pow()进行基准测试。

答案 1 :(得分:2)

对于您的具体情况(“为多个b计算一次a”),我建议采用以下方法:

准备稍后在特定计算中使用的表格数据:

  • 确定N使得每个可能的b的2 ^ N小于b。

  • 计算表t:t [n] = a ^(2 ^ n),每个n小于N.这有效地完成为t [k + 1] = t [k] * t [ K]

计算a ^ b:

  • 使用b的二进制表示,计算a ^ b为t [i1] t [i2] ... * t [ik]其中i1..ik是非零位的位置b。的二进制表示。

这个想法是为不同的b重用a ^(2 ^ n)的值。

答案 2 :(得分:0)

当指数是整数时,

Apache FastMath提供double pow(double d, int e)函数。

implementation is based on Veltkamp's TwoProduct algorithm。用法类似于标准Math.pow函数:

import org.apache.commons.math3.util.FastMath;
// ...
FastMath.pow(3.1417, 2);