簡體   English   中英

"在 Java 中求解三次方程時遇到問題"

[英]Having trouble solving cubic equations in Java

我正在嘗試遵循一些偽代碼來解決程序員數學和物理中的三次方程,第 3 章,據我所知,我已經准確地遵循了它,但我似乎沒有得到正確的輸出。

例如:根據 Wolfram Alpha 5x^3 + 4x^2 + 3x + 2 = 0 應該給出 x≈-0.72932 的根,但我從腳本中返回 -1.8580943294965526。

有人可以幫我弄清楚我在做什么嗎? 我正在按照腳本更好地理解數學並將方程式轉換為代碼。 但這是我理解的邊緣,所以我發現調試起來很麻煩。 再加上這本書沒有勘誤表,而且許多在線評論表明這本書有很多錯誤,我很難確定問題出在我的代碼、書籍解釋還是兩者兼而有之。

書中給出的等式是:

情商

那么如果判別式 > 0 則 root 的值為 r+s:

D1

如果判別式 == 0 則有兩個根:

D2

如果判別式 < 0,您可以找到三個根,如下所示:

D3

找到t后,您可以通過以下方式將其轉換為x

轉變

package com.oacc.maths;

public class SolveCubic {

    public static double[] solveCubic(double a, double b, double c, double d) {
        double[] result;
        if (d != 1) {
            a = a / d;
            b = b / d;
            c = c / d;
        }

        double p = b / 3 - a * a / 9;
        double q = a * a * a / 27 - a * b / 6 + c / 2;
        double D = p * p * p + q * q;

        if (Double.compare(D, 0) >= 0) {
            if (Double.compare(D, 0) == 0) {
                double r = Math.cbrt(-q);
                result = new double[2];
                result[0] = 2 * r;
                result[1] = -r;
            } else {
                double r = Math.cbrt(-q + Math.sqrt(D));
                double s = Math.cbrt(-q - Math.sqrt(D));
                result = new double[1];
                result[0] = r + s;
            }
        } else {
            double ang = Math.acos(-q / Math.sqrt(-p * p * p));
            double r = 2 * Math.sqrt(-p);
            result = new double[3];
            for (int k = -1; k <= 1; k++) {
                double theta = (ang - 2 * Math.PI * k) / 3;
                result[k + 1] = r * Math.cos(theta);
            }

        }
        for (int i = 0; i < result.length; i++) {
            result[i] = result[i] - a / 3;
        }
        return result;
    }


    public static double[] solveCubic(double a, double b, double c) {
        double d = 1;
        return solveCubic(a, b, c, d);
    }

    public static void main(String args[]) {
        double[] result = solveCubic(5, 4, 3, 2);
        for (double aResult : result) {
            System.out.println(aResult);
        }
    }
}

我還從本書網站上找到了這個代碼示例(注意這不是書中的偽代碼): http ://www.delmarlearning.com/companions/content/1435457331/files/index.asp?isbn=1435457331

 on solveCubic(a,b,c,d)
 --! ARGUMENTS: 
a, b, c, d (all numbers). d is optional (default is 1)
 --! 
RETURNS: the list of solutions to dx^3+ax^2+bx+c=0


-- if d is defined then divide a, b and c by d 
 if not voidp(d) 
then
 if d=0 then return solveQuadratic(b,c,a)

set d to float(d)
 set a to a/d
 set b to b/d
 set 
c to c/d
 else
 set a to float(a)
 set b to float(b)

 set c to float(c)
 end if

 set p to b/3 - a*a/9

 set q to a*a*a/27 - a*b/6 + c/2
 set disc to p*p*p + q*q


 if abs(disc)<0.001 then 
 set r to cuberoot(-q)
 set ret to [2*r, -r]
 else if disc>0 then
 set r to cuberoot(-q+sqrt(disc))
 set s to cuberoot(-q-sqrt(disc))

set ret to [r+s]
 else

 set ang to acos(-q/sqrt(-p*p*p))
 set r to 2*sqrt(-p)

set ret to []
 repeat with k=-1 to 1
 set theta 
to (ang - 2*pi*k)/3
 ret.add(r*cos(theta))
 end repeat

end if
 set ret to ret-a/3 --NB: this adds the value to each 
element
 return ret
end 

該錯誤似乎與您的solveCubic方法的參數名稱有關。

看來您的書正在解釋如何求解方程x 3 + ax 2 + bx + c =0。您在調用方法時認為參數abcd用於方程ax 3 + bx 2 + cx + d =0。但是,事實證明,您的方法主體實際上是在尋找方程dx 3 + ax 2 + bx + c = 0的解。

除了此命名錯誤之外,計算似乎是正確的。 如果您不相信我,請嘗試將≈-1.858的值插入2x 3 + 5x 2 + 4x + 3。

如果您改為將您的solveCubic方法聲明為

public static double[] solveCubic(double d, double a, double b, double c) {

然后,這些參數對應於方程dx 3 + ax 2 + bx + c。 然后,您應該發現您的方法可以為您提供期望的答案。

好的。 因此,首先,本書中的方程式似乎是在指這個想法:如果您有以下形式的方程式:

x ^ 3 + ax ^ 2 + bx + c = 0

然后通過將t定義為x-(a / 3),您可以將其轉換為沒有二次項的方程,這已由Mathematica進行了驗證:

Mathematica喃喃自語

一旦沒有二次項,就可以應用給定的方法; q為常數項的一半,設p為第一個冪項的系數的三分之一,並將D (判別式)定義為p*p*p - q*q

然后所有其他內容都將遵循。

那么為什么您的代碼不起作用? 因為您沒有正確標記變量。 ax^2而不是x^3的系數。 如果使用參數(0.8、0.6、0.4、1)或等效地使用(4、3、2、5)調用方法,則將獲得正確的答案。

(或者按照其他答案的建議進行操作,並在方法聲明中圍繞變量名進行更多操作)

公共無效solveCubicEquation(int A,int B,int C,int D){

    double a = (double) B / A;
    double b = (double) C / A;
    double c = (double) D / A;

    System.out.println("Double values: ");
    System.out.println(a + " " + b + " " + c);
    double p = b - ((a * a) / 3.0);

    double q = (2 * Math.pow(a, 3) / 27.0) - (a * b / 3.0) + c;

    double delta = (Math.pow(q, 2) / 4) + (Math.pow(p, 3) / 27);

    if (delta > 0.001) {

        double mt1, mt2;

        double t1 = (-q / 2.0) + Math.sqrt(delta);
        double t2 = (-q / 2.0) - Math.sqrt(delta);

        if (t1 < 0) {
            mt1 = (-1) * (Math.pow(-t1, (double) 1 / 3));
        } else {
            mt1 = (Math.pow(t1, (double) 1 / 3));
        }

        if (t2 < 0) {
            mt2 = (-1) * (Math.pow(-t2, (double) 1 / 3));
        } else {
            mt2 = (Math.pow(t2, (double) 1 / 3));
        }

        x1 = mt1 + mt2 - (a / 3.0);

    } else if (delta < 0.001 && delta > -0.001) {

        if (q < 0) {

            x1 = 2 * Math.pow(-q / 2, (double) 1 / 3) - (a / 3);
            x2 = -1 * Math.pow(-q / 2, (double) 1 / 3) - (a / 3);

        } else {
            x1 = -2 * Math.pow(q / 2, (double) 1 / 3) - (a / 3);
            x2 = Math.pow(q / 2, (double) 1 / 3) - (a / 3);

        }

    } else {

        System.out.println("here");
        x1 = (2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.sin((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))))) - (a / 3.0);
        x2 = (-2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.sin((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))) + (Math.PI / 3))) - (a / 3.0);
        x3 = (2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.cos((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))) + (Math.PI / 6))) - (a / 3.0);

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM