Java有效地改进代码

时间:2014-12-17 13:45:17

标签: java performance math

我在我的一个程序中使用了以下功能。

我试图确保我的代码有效但是我在网上找不到任何帮助告诉我如何识别我可以改进的地方......

是否有任何一个可以帮助确定是否有任何可以改进的部分(加快速度)或更高效地运行

z,s和t都是整数

powerMod(z, s, t) {
    int temp = 1;
    while (s > 0) {
        temp = temp * z;
        s = s - 1;
    }
    temp = temp mod t;
    return temp;
}

所以这个的整体功能也是将z计算为s的幂,然后每次将其修改为n。非常简单,但我无法弄清楚如何让它更快,因为它将被主程序100s或1000次使用

5 个答案:

答案 0 :(得分:2)

这样的事情?

使用exponentiation by square和ive使用long只是因为int * int而导致溢出...

 int powMod(int z, int s, int t){
        long result = 1; //int * int will never exceed the size of a long
        long multiplicant = z;
        while(s > 0){
            if(s % 2 == 1) {
                result *= multiplicant;
                result %= t; // do modulo on each temporary result to keep accuracy
            }

            multiplicant *= multiplicant;
            multiplicant %= t;
            s /= 2;

        }
        return result;
    }

答案 1 :(得分:1)

首先,请注意您的代码将无法执行您的描述要求对大型输入执行的操作:

  

...所以这个的整体功能太过计算z的功率了   然后每次用n修改它。 ...

但请注意,由于integer overflow,您的代码会因大值而中断,因为您将首先尝试计算一个很大的数字,这可能会溢出 - 然后才会调用模式运算符。< / p>

计算上述内容的正确方法是使用以下事实:

(x*x*x*...*x) mod t == (...(((x mod t)*x) mod t)*...*x) mod t

第二次计算将为更大的输入产生正确的答案,只需要假设是x*t <= Integer.MAX_VALUE,这是一个更简单的假设。

至于您提高性能的要求 - 使用exponent by squaring有效地计算功率运算符。确保在此方法中使用上述等式,以避免大输入的错误。

另一个解决方案是使用java的BigInteger库,特别是方法BigInteger.modPow()

答案 2 :(得分:0)

不要构建自己的运算符,而是尝试使用Math.pow()(并添加mod部分)。

答案 3 :(得分:0)

为什么不使用数学?对我来说似乎是最快捷的方式。

powerMod(double z, double s, double t)
{
    double a = Math.pow(z, s);
    return Math.floorMod(a, t);
}

答案 4 :(得分:0)

如果您真的关注性能,可以使用Guava.IntMath.pow()在O(log(n))时间内取幂。该实现的源代码如下:

public static int pow(int b, int k) {
    checkNonNegative("exponent", k);
    switch (b) {
      case 0:
        return (k == 0) ? 1 : 0;
      case 1:
        return 1;
      case (-1):
        return ((k & 1) == 0) ? 1 : -1;
      case 2:
        return (k < Integer.SIZE) ? (1 << k) : 0;
      case (-2):
        if (k < Integer.SIZE) {
          return ((k & 1) == 0) ? (1 << k) : -(1 << k);
        } else {
          return 0;
        }
      default:
        // continue below to handle the general case
    }
    for (int accum = 1;; k >>= 1) {
      switch (k) {
        case 0:
          return accum;
        case 1:
          return b * accum;
        default:
          accum *= ((k & 1) == 0) ? 1 : b;
          b *= b;
      }
    }
  }

您还应该注意,在大多数实际情况下,常规Math.pow()足以满足您的解决方案。你应该考虑交换算法,如果它真的会减慢你的程序。