在 C# 中计算三次方程的问题
Problem with calculating cubic equations in C#
最近我在开发一个 discord 机器人来计算三次方程的根。
我已经事先用 C# 编写了另一个程序,基本上做同样的事情,证明可以正常工作,所以我直接将代码复制到我现在正在工作。
(假设我正在计算 7x3 + 2x2 + 的根12x + 9 = 0)
下面的代码来自预先创建的程序:
(再次证明程序和结果 是正确的,结果列在代码底部) *
// parts 1-5
double p1 = -(b / (3 * a));
double p2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double p3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
Complex p4 = new Complex(-1.0 / 2, Math.Sqrt(3) / 2);
Complex p5 = new Complex(-1.0 / 2, -(Math.Sqrt(3) / 2));
// solve for roots
Complex root1 = p1 + Math.Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))) +
Math.Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)));
Complex root2 = p1 + (p4 * Math.Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p5 * Math.Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
Complex root3 = p1 + (p5 * Math.Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p4 * Math.Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
/*
results :
root1 = (-0.6566823203779361, 0)
root2 = (0.18548401733182518, 1.3868992549529795)
root3 = (0.18548401733182518, -1.3868992549529795)
*/
我继续将整个内容复制到我正在处理的新程序中。然后我意识到在我的新程序中 Math.Cbrt 函数不存在 (我不知道为什么)。因此我制作了一个自定义程序来解决这个问题,这是我新程序中的代码:
(这是有问题的程序,结果和第一个不一样。)
// parts 1-5
double p1 = -(b / (3 * a));
double p2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double p3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
Complex p4 = new Complex(-1.0 / 2, Math.Sqrt(3.0) / 2);
Complex p5 = new Complex(-1.0 / 2, -(Math.Sqrt(3.0) / 2));
// solve for roots
Complex root1 = p1 + Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))) +
Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)));
Complex root2 = p1 + (p4 * Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p5 * Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
Complex root3 = p1 + (p5 * Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p4 * Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
public static Complex Cbrt(Complex value)
{
Complex result = Complex.Pow(value, 1D / 3);
return result;
}
/*
results :
root1 = (0.965490835755936, 0.936562108366076)
root2 = (0.185484017331825, -0.486224961779172)
root3 = (-1.43668913880205, -0.450337146586904)
*/
我尝试提取代码的不同部分并 运行 分开,但我仍然无法找到原因。如果代码相同,为什么它们会产生不同的结果?还是我创建的Cbrt方法才是真正的问题所在?
参考@mikuszefski 的评论,
这背后的真正原因是我创建的 Cbrt() 函数错误地计算了 负数。
例如,Cbrt(-1)
应该产生结果 -1
。
然而,我得到的答案却是 (NaN, 0)
.
我在 .
中找到了解决方案
最近我在开发一个 discord 机器人来计算三次方程的根。
我已经事先用 C# 编写了另一个程序,基本上做同样的事情,证明可以正常工作,所以我直接将代码复制到我现在正在工作。
(假设我正在计算 7x3 + 2x2 + 的根12x + 9 = 0)
下面的代码来自预先创建的程序:
(再次证明程序和结果 是正确的,结果列在代码底部) *
// parts 1-5
double p1 = -(b / (3 * a));
double p2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double p3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
Complex p4 = new Complex(-1.0 / 2, Math.Sqrt(3) / 2);
Complex p5 = new Complex(-1.0 / 2, -(Math.Sqrt(3) / 2));
// solve for roots
Complex root1 = p1 + Math.Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))) +
Math.Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)));
Complex root2 = p1 + (p4 * Math.Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p5 * Math.Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
Complex root3 = p1 + (p5 * Math.Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p4 * Math.Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
/*
results :
root1 = (-0.6566823203779361, 0)
root2 = (0.18548401733182518, 1.3868992549529795)
root3 = (0.18548401733182518, -1.3868992549529795)
*/
我继续将整个内容复制到我正在处理的新程序中。然后我意识到在我的新程序中 Math.Cbrt 函数不存在 (我不知道为什么)。因此我制作了一个自定义程序来解决这个问题,这是我新程序中的代码:
(这是有问题的程序,结果和第一个不一样。)
// parts 1-5
double p1 = -(b / (3 * a));
double p2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double p3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
Complex p4 = new Complex(-1.0 / 2, Math.Sqrt(3.0) / 2);
Complex p5 = new Complex(-1.0 / 2, -(Math.Sqrt(3.0) / 2));
// solve for roots
Complex root1 = p1 + Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))) +
Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)));
Complex root2 = p1 + (p4 * Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p5 * Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
Complex root3 = p1 + (p5 * Cbrt(p2 + Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3)))) +
(p4 * Cbrt(p2 - Math.Sqrt(Math.Pow(p2, 2) + Math.Pow(p3, 3))));
public static Complex Cbrt(Complex value)
{
Complex result = Complex.Pow(value, 1D / 3);
return result;
}
/*
results :
root1 = (0.965490835755936, 0.936562108366076)
root2 = (0.185484017331825, -0.486224961779172)
root3 = (-1.43668913880205, -0.450337146586904)
*/
我尝试提取代码的不同部分并 运行 分开,但我仍然无法找到原因。如果代码相同,为什么它们会产生不同的结果?还是我创建的Cbrt方法才是真正的问题所在?
参考@mikuszefski 的评论,
这背后的真正原因是我创建的 Cbrt() 函数错误地计算了 负数。
例如,Cbrt(-1)
应该产生结果 -1
。
然而,我得到的答案却是 (NaN, 0)
.
我在