web-dev-qa-db-ja.com

nが偶数の場合に最適化されたx ^ nの再帰的方法

Java double xと整数nを取り、x ^ nを返すpowerと呼ばれる再帰的メソッドを書く必要があります。これまでのところ、以下のようになります。

public static double power(double x, int n) {
    if (n == 0)
        return 1;
    if (n == 1)
        return x;
    else
        return x * (power(x, n-1));

}

このコードは期待どおりに動作します。ただし、私はさらに一歩進んで、次のオプションの演習を実行しようとしています。

「オプションの課題:nが偶数の場合、x ^ n =(x ^(n/2))^ 2を使用して、この方法をより効率的にすることができます。」

Nが偶数のときに最後の式を実装する方法がわかりません。そのために再帰を使用できるとは思いません。私は以下を実装しようとしましたが、intのパワーにdoubleを取ることができないため、それも機能しません。

if (n%2 == 0)
        return (x^(n/2))^2;

誰かが私を正しい方向に向けることができますか?明らかな何かが欠けているように感じます。すべての助けに感謝します。

37
Omar N

これは、x ^ n == x *(x ^(n-1))の場合とまったく同じ原理です:x ^(n/2)と(...)^ 2の再帰関数を挿入しますが、 n == 2に対して無限再帰を入力しない(2も偶数であるため):

if (n % 2 == 0 && n > 2) 
  return power(power(x, n / 2), 2);
} 

または、中間変数を使用することもできます。

if (n % 2 == 0) {
  double s = power(x, n / 2);
  return s * s;
}

私もおそらく2を特別なケースとして扱うだけです-そして、 "and"条件と余分な変数を避けます:

public static double power(double x, int n) {
  if (n == 0) return 1;
  if (n == 1) return x;
  if (n == 2) return x * x;
  if (n % 2 == 0) return power(power(x, n / 2), 2);
  return x * (power(x, n - 1));
}

追伸これもうまくいくと思います:)

public static double power(double x, int n) {
  if (n == 0) return 1;
  if (n == 1) return x;
  if (n == 2) return x * x;
  return power(x, n % 2) * power(power(x, n / 2), 2);
}
23
Stefan Haustein

nが偶数の場合、式は記述したとおりです。nを2で割り、powerを再帰的に呼び出し、結果を二乗します。

nが奇数の場合、式は少し複雑になります。nから1を減算し、n/2を再帰的に呼び出し、結果を2乗し、乗算します。 x

if (n%2 == 0)
    return (x^(n/2))^2;
else
    return x*(x^(n/2))^2;

n/2は結果を切り捨てるため、1の減算は明示的に行われません。 Javaでの実装は次のとおりです。

public static double power(double x, int n) {
    if (n == 0) return 1;
    if (n == 1) return x;
    double pHalf = power(x, n/2);
    if (n%2 == 0) {
        return pHalf*pHalf;
    } else {
        return x*pHalf*pHalf;
    }
}

デモ

11
dasblinkenlight

ヒント:^操作はJavaで指数を実行しませんが、作成した関数powerは実行します。

また、数を2乗することは、それ自体を乗算することと同じです。関数呼び出しは必要ありません。

6
jaynp

関数に小さな変更を加えると、行われる再帰呼び出しの数が減ります。

public static double power(double x, int n) {
    if (n == 0) {
        return 1;
    }
    if (n == 1) {
        return x;
    }

    if (n % 2 == 0) {
        double temp = power(x, n / 2);
        return temp * temp;
    } else {
        return x * (power(x, n - 1));
    }
}
6
sstan

以来

x^(2n) = (x^n)^2

stefan Hausteinが提案したように、記述したべき関数を使用するか、通常の乗算​​演算子を使用して、このルールをメソッドに追加できます。

基本ケースn = 1とn = 0の両方の必要はなく、そのうちの1つで十分であることに注意してください(それ以外の場合、メソッドはn = 0に対して定義されないため、基本ケースn = 0を使用することが好ましい)。

public static double power(double x, int n) {
    if (n == 0)
        return 1;
    else if (n % 2 == 0)
        double val = power(x, n/2);
        return val * val;
    else
        return x * (power(x, n-1));
}

いずれの場合も、n> 2であることを確認する必要はありません。

5
carlos

これは、より多くの最適化を行うことができ、次のコードを思い出させるだけです。

class Solution:
# @param x, a float
# @param n, a integer
# @return a float
def pow(self, x, n):
    if n<0:
        return 1.0/self.pow(x,-n)
    Elif n==0:
        return 1.0
    Elif n==1:
        return x
    else:
        m = n & (-n)
        if( m==n ):
            r1 = self.pow(x,n>>1)
            return r1*r1
        else:
            return self.pow(x,m)*self.pow(x,n-m)

より中間的な結果は何が記憶され、冗長な計算を避けることができます。

0
zinking