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表示。为了满足 ax 2 +bx+c = 0,你得到/ 2a 作为答案。bc(-b +/- sqrt(b^2-4ac))

我认为您的基本问题是您出于某种原因使用模数而不是平方根。-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 转换为整数?它是给你平方函数根的方程,所以 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

你为什么做模而不是平方根?您的代码似乎是获得二次方程根的方法 ((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 回答
0

正如其他人所指出的,您对 mod 的使用甚至没有错。你为什么要编成这样的数学?

众所周知,如果 b 的值非常接近判别式,则二次方程的朴素解可能会出现问题。

“C++ 中的数值配方”第 5.6 节建议了一种更好的方法:如果我们定义

替代文字
(来源:equationsheet.com

那么这两个根是:

替代文字

替代文字

您的代码还需要考虑病理情况(例如,a = 0)。

让我们将您的值代入这些公式,看看我们得到了什么。如果 a = 10、b = 7 和 c = 10,则:

替代文字
(来源:equationsheet.com

那么这两个根是:

替代文字
(来源:equationsheet.com

替代文字
(来源:equationsheet.com

我想我的迹象是正确的。

如果您的计算给您带来麻烦,很可能是由于您的方法无法正确考虑复杂的根源。你需要一个复数类。

于 2009-11-29T15:35:01.750 回答