我试图按照一些伪代码来解决程序员数学和物理中的立方方程,第3章,据我所知,我已经准确地遵循了它,但我不是似乎得到了正确的输出。
例如:根据Wolfram Alpha 5x ^ 3 + 4x ^ 2 + 3x + 2 = 0应该给出x≈-0.72932的根,但是我从我的脚本中返回-1.8580943294965526。
有人可以帮我弄清楚我到底在干嘛?我按照脚本来更好地理解数学并将方程式转换为代码。但这是我理解的边缘,所以我发现调试很麻烦。再加上这本书没有勘误,而且许多在线评论都说这本书有很多错误,我很难看出这个问题是关于我的代码,书籍解释还是两者兼而有之。
书中给出的等式是:
然后,如果判别式> 0然后root的值为r + s:
如果判别式== 0则有两个根:
如果判别< 0您可以按如下方式找到三个根:
找到 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);
}
}
}
我还在图书网站上找到了这个代码示例(n.b。这不是书中的伪代码):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
答案 0 :(得分:1)
错误似乎与`var prefs: SettingsController? = nil
@IBAction func OpenPreferences(_ sender: Any) {
DispatchQueue.main.async(execute: { () -> Void in
NSApplication.shared().runModal(for: (self.prefs?.window)!)
})
}`
func applicationDidFinishLaunching(_ aNotification: Notification)
{
// Insert code here to initialize your application
prefs = SettingsController()
}`
方法的参数名称有关。
看来你的书正在解释如何解决方程式x 3 + ax 2 + bx + c = 0.你正在调用你的方法认为参数{ {1}},solveCubic
,a
和b
用于等式ax 3 + bx 2 + cx + d =然而,事实证明,你的方法的主体实际上找到了方程dx 3 + ax 2 + bx + c = 0的解。
除了这个命名错误,计算似乎是正确的。如果你不相信我,试着将你的值≈-1.858插入2x 3 + 5x 2 + 4x + 3。
如果您改为将c
方法声明为
d
然后,参数对应于等式dx 3 + ax 2 + bx + c。然后,您应该发现您的方法可以为您提供所期望的答案。
答案 1 :(得分:1)
好。所以,首先从书中的方程似乎是指这个想法:如果你有一个形式的等式:
然后通过将 t 定义为 x - (a / 3),您可以将其转换为没有二次项的等式,由一些验证数学:
如果没有二次项,则可以应用给定的方法;让 q 为常数项的一半,让 p 为第一个幂项的系数的三分之一,并将 D (判别式)定义为{ {1}}。
其他一切都随之而来。
那为什么你的代码不起作用?因为你错误地标记了变量。 a 是p*p*p - q*q
上的系数,而不是x^2
上的系数。如果你使用参数(0.8,0.6,0.4,1)调用你的方法或者等同于(4,3,2,5)你的方法,你将得到正确的答案。
(或者如同其他答案所示,并且更多地围绕方法声明中的变量名称)