4

私はJavaで次の作業方法を持っています:

/**
 * Determines if n is a power of z
 * 
 * @param z the number that n may be a power of
 * @param n the number that may be a power of z
 * @return true if n is a power of z 
 */
public boolean isPowerOf(int z, int n) {
    double output = Math.log(n) / Math.log(z);
    if(output % 1 > 0) {
        return false;
    } else {
        return true;
    }
}

isPowerOf(3, 729); //returns true, because 3^6 = 729

うまく動作しますが、最初は別の方法で試しました:

public boolean isPowerOf(int z, int n) {
    double output = Math.log(n) % Math.log(z);
    if(output != 0) {
        return false;
    } else {
        return true;
    }
}

しかし、 forlog(729) % log(3)は を返すようですが1.0986122886681093、 の結果はlog(729) / log(3) is 6.

モジュロ演算子がまだ1.09ここで剰余を与える原因を教えてくれる人はいますか?

4

2 に答える 2

7

ここでモジュロ演算子がまだ 1.09 の剰余を与える原因を教えてくれる人はいますか?

基本的に、通常の浮動小数点の不正確さ。使用している値は、正確にはlog(729) と log(3) ではありません。見てみるとlog(3)log(729) % log(3)ほとんど同じであることがわかります。

public class Test {
    public static void main(String[] args) {
        double x = Math.log(729);
        double y = Math.log(3);
        System.out.println(x);
        System.out.println(y);
        System.out.println(x % y);
    }
}

出力:

6.591673732008658
1.0986122886681098
1.0986122886681093

言い換えれば、log(729)効果的log(3) * 5.9999999999999(または同様のもの) です。基本的に、テストにある程度の許容範囲を追加し、残りが0 に非常に近いかどうか、またはに非常log(z)に近いかどうかを返したいと思うでしょう。

または、 と 除算を使用logして、べき乗を「大まかに」計算してMath.powから、正確な値を確認します。

int power = (int) (Math.log(n) / Math.log(z) + 0.5);
return n == Math.pow(z, power);

ここでは、数値が「かなり大きく」なるまで、浮動小数点の不正確さに関しては問題ありません。非常に大きな数を正確に処理BigIntegerしたい場合に使用できます。

于 2012-10-23T13:47:46.360 に答える
2
Math.log(729)  = 6.591673732008658
Math.log(3) = 1.0986122886681098

d= 1.0986122886681093

お気づきの場合d (1.0986122886681093)は、付加価値よりわずかに小さい (最後の桁) ですが 、正常Math.log(3)-(1.0986122886681098)に機能しているようです。おそらく、double データ型の精度を理解していないでしょう。浮動小数点数は、実際の表現が原因で、高精度の値に対して不正確な点があります。

于 2012-10-23T13:48:26.733 に答える