2

私は単純な方程式を実装しようとしています:

i,j = -Q ± √(Q 2 -4PR) / 2P

そうするために、私は次のコードを持っています (注: P = 10. Q = 7. R = 10):

    //Q*Q – 4PR = -351 mod 11 = -10 mod 11 = 1, √1 = 1
    double test = Math.sqrt(modulo(((Q*Q) - ((4*P)*R))));

    // Works, but why *-10 needed?
    i = (int)(((-Q+test)/(P*2))*-10);    // i = 3
    j = (int)(((-Q-test)/(P*2))*-10);    // j = 4

簡単に言うと、test は方程式の最初の部分を取り、それを 0 から 11 の間のゼロ以外の整数に変更してから、i と j を書き込みます。i と j は正しい数値を返しますが、何らかの理由で、それらを正しくするには *-10 が必要です (正しい値を得るために私が推測した数値)。

可能であれば、上記の式を実行するより良い方法を見つけたいと思います。私のやり方は間違っているようで、うまくいくからです。ハッキングして機能させるのではなく、方程式が示すように実行したいと思います。

4

5 に答える 5

6

次方程式aは、より通常、 、bおよびで表されcます。ax 2 +bx+c = 0を満たすために(-b +/- sqrt(b^2-4ac))、答えとして / 2a が得られます。

あなたの基本的な問題は、平方根を取る代わりに何らかの理由でモジュロを使用していることだと思います。-10 という係数は、たまたまテスト ケースで機能するファッジ係数です。

次のようなものが必要です。

public static void findRoots(double a, double b, double c)
{
    if (b * b < 4 * a * c)
    {
        throw new IllegalArgumentException("Equation has no roots");
    }

    double tmp = Math.sqrt(b * b - 4 * a * c);
    double firstRoot = (-b + tmp) / (2 * a);
    double secondRoot = (-b - tmp) / (2 * a);
    System.out.println("Roots: " + firstRoot + ", " + secondRoot);
}

編集:あなたのmoduloメソッドは現在、かなり慢性的に再帰しようとしています。代わりにこれを試してください:

public static int modulo(int x)
{
    return ((x % 11) + 11) % 11;
}

基本的に、最初の結果は% 11[-10, 10] の範囲になります。そのため、さらに 11 を追加して% 11 再度取得すると、正しい結果になります。再帰する必要はありません。

その時点で、それを別の方法として使用する理由はあまりないので、次を使用できます。

public static void findRoots(double a, double b, double c)
{       
    int squareMod11 = (((b * b - 4 * a * c) % 11) + 11) % 11;
    double tmp = Math.sqrt(squareMod11);
    double firstRoot = (-b + tmp) / (2 * a);
    double secondRoot = (-b - tmp) / (2 * a);
    System.out.println("Roots: " + firstRoot + ", " + secondRoot);
}
于 2009-11-29T12:44:38.497 に答える
1

平方根を取る必要があります。Q^2-4PR は負の数を生成するため、複素数を処理する (またはこのシナリオを回避するために入力を制限する) 必要があることに注意してください。ここではApache Mathが役に立ちます。

于 2009-11-29T12:44:49.940 に答える
1

平方根には Math.sqrt を使用します。i と j を int にキャストするのはなぜですか? これは二乗関数の根を与える方程式なので、i と j は任意の複素数にすることができます。判別式を実 (倍精度) 根の正の値のみに制限する必要があります。それ以外の場合は、複素数を使用します。


double test = Q*Q - 4*P*R;
if(Q < 0) throw new Exception("negative discriminant!");
else {
    test = Math.sqrt(test);
    double i = (-Q + test) / 2*P;
    double i = (-Q - test) / 2*P;
}
于 2009-11-29T12:47:50.040 に答える
0

他の人が指摘したように、mod の使用は間違っていません。なぜ、このような数学をでっちあげているのですか?

b の値が判別式にほぼ等しい場合、二次方程式の単純な解に問題が生じる可能性があることはよく知られています。

それを行うためのより良い方法は、「C++ の数値レシピ」のセクション 5.6 で提案されています。

代替テキスト
(出典:equationsheet.com

次に、2 つのルートは次のとおりです。

代替テキスト

代替テキスト

コードは、異常なケース (a = 0 など) も考慮する必要があります。

これらの式に値を代入して、結果を見てみましょう。a = 10、b = 7、および c = 10 の場合、次のようになります。

代替テキスト
(出典:equationsheet.com

次に、2 つのルートは次のとおりです。

代替テキスト
(出典:equationsheet.com

代替テキスト
(出典:equationsheet.com

私は正しい兆候を持っていると思います。

計算で問題が発生する場合は、メソッドが適切に考慮できない複雑なルートがあることが原因である可能性があります。複素数クラスが必要です。

于 2009-11-29T15:35:01.750 に答える
0

なぜ平方根ではなくモジュロを行うのですか? あなたのコードは、二次方程式 ((a±sqrt(b^2-4ac))/2a) の根を取得する方法のように思われるため、コードは次のようになります。

double delta = Q*Q-4*P*R);
if(delta < 0.0) {
  throw new Exception("no roots");
}
double d = Math.power(delta,0.5);
double r1 = (Q + d)/(2*P)
double r2 = (Q - d)/(2*P)
于 2009-11-29T12:48:40.723 に答える