Javascript 解析解三次方程的函数
我需要解析地和实数地解一个三次方程(ax^3+bx^2+c*x+d=0),最好是用纯javascript(无libs)。由于可能有1到3个根,我认为数字数组是一种合理的结果类型Javascript 解析解三次方程的函数,javascript,algorithm,math,Javascript,Algorithm,Math,我需要解析地和实数地解一个三次方程(ax^3+bx^2+c*x+d=0),最好是用纯javascript(无libs)。由于可能有1到3个根,我认为数字数组是一种合理的结果类型 p.S.在下面提供了我自己的解决方案,希望它会有用。给你。包括处理退化案件。主要算法主要是从 函数cuberoot(x){ 变量y=数学功率(数学绝对值(x),1/3); 返回x
p.S.在下面提供了我自己的解决方案,希望它会有用。给你。包括处理退化案件。主要算法主要是从
函数cuberoot(x){
变量y=数学功率(数学绝对值(x),1/3);
返回x<0?-y:y;
}
函数(a、b、c、d){
如果(数学abs(a)<1e-8){//二次型,ax^2+bx+c=0
a=b;b=c;c=d;
如果(数学abs(a)<1e-8){//线性情况,ax+b=0
a=b;b=c;
if(Math.abs(a)<1e-8)//退化情形
返回[];
返回[-b/a];
}
变量D=b*b-4*a*c;
if(数学abs(D)<1e-8)
回报率[-b/(2*a)];
否则,如果(D>0)
返回[(-b+数学sqrt(D))/(2*a),(-b-数学sqrt(D))/(2*a)];
返回[];
}
//转换为下压立方t^3+pt+q=0(子矩阵x=t-b/3a)
var p=(3*a*c-b*b)/(3*a*a);
变量q=(2*b*b*b-9*a*b*c+27*a*a*d)/(27*a*a*a*a);
变种根;
if(Math.abs(p)<1e-8){//p=0->t^3=-q->t=-q^1/3
根=[cuberoot(-q)];
}如果(数学abs(q)<1e-8){//q=0->t^3+pt=0->t(t^2+p)=0
根=[0].concat(p<0?[Math.sqrt(-p),-Math.sqrt(-p)]:[]);
}否则{
var D=q*q/4+p*p*p/27;
if(Math.abs(D)<1e-8){//D=0->两个根
根=[-1.5*q/p,3*q/p];
}else如果(D>0){//只有一个实根
var u=cuberoot(-q/2-数学sqrt(D));
根=[u-p/(3*u)];
}else{//D<0,三个根,但需要使用复数/三角解
var u=2*数学sqrt(-p/3);
var t=Math.acos(3*q/p/u)/3;//D<0表示p<0,acos参数在[-1..1]
var k=2*Math.PI/3;
根=[u*Math.cos(t),u*Math.cos(t-k),u*Math.cos(t-2*k)];
}
}
//从下压立方转换回
对于(var i=0;i
Complex root?这个问题似乎离题了,因为它是关于让别人为你做工作的。@duffymo:注意,答案是同一个用户;事实上,他正在做这项工作,并将其发布在这里,我认为这个问题似乎是一个要求。谢谢@PhilH,我编辑了这个问题,明确表示我已经完成了这项工作,并将其分享给大家。假设它能起作用,这是写作的道具!我可能建议你编辑这个问题;我认为它吸引了反对票,因为它似乎要求一个没有工作的答案,而事实上你在这里提供答案,你已经完成了工作!硬编码ε是一个糟糕的做法。非常感谢。我把它移植到php,它工作得很好。我找到的最佳解决方案。为什么要使用“是”,以避免舍入错误。请根据您的应用需要随时调整ε。
function cuberoot(x) {
var y = Math.pow(Math.abs(x), 1/3);
return x < 0 ? -y : y;
}
function solveCubic(a, b, c, d) {
if (Math.abs(a) < 1e-8) { // Quadratic case, ax^2+bx+c=0
a = b; b = c; c = d;
if (Math.abs(a) < 1e-8) { // Linear case, ax+b=0
a = b; b = c;
if (Math.abs(a) < 1e-8) // Degenerate case
return [];
return [-b/a];
}
var D = b*b - 4*a*c;
if (Math.abs(D) < 1e-8)
return [-b/(2*a)];
else if (D > 0)
return [(-b+Math.sqrt(D))/(2*a), (-b-Math.sqrt(D))/(2*a)];
return [];
}
// Convert to depressed cubic t^3+pt+q = 0 (subst x = t - b/3a)
var p = (3*a*c - b*b)/(3*a*a);
var q = (2*b*b*b - 9*a*b*c + 27*a*a*d)/(27*a*a*a);
var roots;
if (Math.abs(p) < 1e-8) { // p = 0 -> t^3 = -q -> t = -q^1/3
roots = [cuberoot(-q)];
} else if (Math.abs(q) < 1e-8) { // q = 0 -> t^3 + pt = 0 -> t(t^2+p)=0
roots = [0].concat(p < 0 ? [Math.sqrt(-p), -Math.sqrt(-p)] : []);
} else {
var D = q*q/4 + p*p*p/27;
if (Math.abs(D) < 1e-8) { // D = 0 -> two roots
roots = [-1.5*q/p, 3*q/p];
} else if (D > 0) { // Only one real root
var u = cuberoot(-q/2 - Math.sqrt(D));
roots = [u - p/(3*u)];
} else { // D < 0, three roots, but needs to use complex numbers/trigonometric solution
var u = 2*Math.sqrt(-p/3);
var t = Math.acos(3*q/p/u)/3; // D < 0 implies p < 0 and acos argument in [-1..1]
var k = 2*Math.PI/3;
roots = [u*Math.cos(t), u*Math.cos(t-k), u*Math.cos(t-2*k)];
}
}
// Convert back from depressed cubic
for (var i = 0; i < roots.length; i++)
roots[i] -= b/(3*a);
return roots;
}