继续我的最后一个问题:在 C# 中计算四次方程的根时遇到问题
Continuation to my last question : Having trouble in calculating roots of a quartic equation in C#
这个帖子是我的的延续。
我和小伙伴正在尝试做一个可以自动计算的多功能计算器
二次、三次甚至四次方程的根。
但是,我们 运行 遇到了一些问题,以前是三次方程,现在是 四次方程。
与上一个主题不同,我们将提供图像,包括我们程序计算的答案和WolframAlpha计算的答案,而不是将它们放在此处的文本中。
四次方程将表示为
ax^4 + bx^3 + cx^2 + dx + e
Our method of finding the roots of a quartic equation. (在另一个网站的另一个线程中找到)
a=1 b=2 c=-41 d=-42 e=360
a=1 b=-0.25 c=-0.85 d=1.45 e=-4.35
a=1 b=2 c=3 d=4 e=5
如图所示,程序计算的判别式始终正确。但是,方程的根有时会导致错误 (NaN),并且根的性质也会导致错误,但与根一样频繁。
根据以上提供的所有信息,我们希望知道以下问题的答案:
- 究竟是什么导致了这些错误和问题,
- 我应该对我的代码进行什么修改,以便程序可以正常运行,
- 我们求四次方程根的方法是否正确,或者是否有可能通过一般的方法求所有四次方程的根公式,
- 最后但同样重要的是,有没有办法改进,或者压缩我们程序中的代码行,但仍然像我们一样运行打算这样做。
如前一帖所述,我们才刚刚开始学习C#。
为了您的方便,我们对一些代码行做了注释。
代码(C#):
using System;
using System.Numerics;
namespace ComplexNumbers
{
public class ComplexNo
{
public static void Main()
{
// prompting for coefficients and constant
Console.WriteLine("Quartic Equation Calculator :");
Console.Write("Insert first coefficient : ");
double a = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert second coefficient : ");
double b = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert third coefficient : ");
double c = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert fourth coefficient : ");
double d = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert constant : ");
double e = Convert.ToDouble(Console.ReadLine());
// discriminant
double discriminant = 256 * Math.Pow(a, 3) * Math.Pow(e, 3) - (192 * Math.Pow(a, 2) * b * d * Math.Pow(e, 2)) -
(128 * Math.Pow(a, 2) * Math.Pow(c, 2) * Math.Pow(e, 2)) + (144 * Math.Pow(a, 2) * c * Math.Pow(d, 2) * e) -
(27 * Math.Pow(a, 2) * Math.Pow(d, 4)) + (144 * a * Math.Pow(b, 2) * c * Math.Pow(e, 2)) -
(6 * a * Math.Pow(b, 2) * Math.Pow(d, 2) * e) - (80 * a * b * Math.Pow(c, 2) * d * e) +
(18 * a * b * c * Math.Pow(d, 3)) + (16 * a * Math.Pow(c, 4) * e) - (4 * a * Math.Pow(c, 3) * Math.Pow(d, 2)) -
(27 * Math.Pow(b, 4) * Math.Pow(e, 2)) + (18 * Math.Pow(b, 3) * c * d * e) -
(4 * Math.Pow(b, 3) * Math.Pow(d, 3)) - (4 * Math.Pow(b, 2) * Math.Pow(c, 3) * e) +
(Math.Pow(b, 2) * Math.Pow(c, 2) * Math.Pow(d, 2));
// different parts of the roots presented in p1-p6
double p1 = (2 * Math.Pow(c, 3)) - (9 * b * c * d) + (27 * a * Math.Pow(d, 2)) + (27 * Math.Pow(b, 2) * e) -
(72 * a * c * e);
double p2 = p1 + Math.Sqrt(-4.0 * Math.Pow(Math.Pow(c, 2) - (3 * b * d) + (12 * a * e), 3) + Math.Pow(p1, 2));
double p3 = ((Math.Pow(c, 2) - (3 * b * d) + (12 * a * e)) / (3 * a * Math.Cbrt(p2 / 2))) + (Math.Cbrt(p2 / 2) / (3 * a));
double p4 = Math.Sqrt((Math.Pow(b, 2) / (4 * Math.Pow(a, 2))) - (2 * c / (3 * a)) + p3);
double p5 = (Math.Pow(b, 2) / (2 * Math.Pow(a, 2))) - (4 * c / (3 * a)) - p3;
double p6 = ((-(Math.Pow(b, 3) / Math.Pow(a, 3))) + (4 * b * c / Math.Pow(a, 2)) - (8 * d / a)) / (4 * p4);
// calculating roots with p1-p6
Complex x1 = (-(b / (4 * a))) - (p4 / 2) - (Math.Sqrt(p5 - p6) / 2);
Complex x2 = (-(b / (4 * a))) - (p4 / 2) + (Math.Sqrt(p5 - p6) / 2);
Complex x3 = (-(b / (4 * a))) + (p4 / 2) - (Math.Sqrt(p5 - p6) / 2);
Complex x4 = (-(b / (4 * a))) + (p4 / 2) + (Math.Sqrt(p5 - p6) / 2);
// polynomials used for testing the nature of roots
double P = (8 * a * c) - (3 * Math.Pow(b, 2));
double R = Math.Pow(b, 3) + (8 * d * Math.Pow(a, 2)) - (4 * a * b * c);
double deltazero = Math.Pow(c, 2) - (3 * b * d) + (12 * a * e);
double D = (64 * Math.Pow(a, 3) * e) - (16 * Math.Pow(a, 2) * Math.Pow(c, 2)) +
(16 * a * Math.Pow(b, 2) * c) - (16 * Math.Pow(a, 2) * b * d) - (3 * Math.Pow(b, 4));
// results
Console.WriteLine(" ");
Console.WriteLine("Solve for " + a + "x^4 " + " + " + b + "x^3 " + " + " + c + "x^2 " + " + " + d + "x " + " + " + e + " :");
Console.WriteLine(" ");
Console.WriteLine("Results :");
Console.WriteLine("First Root :");
string x1rp = Convert.ToString(Math.Round(x1.Real, 5)); // rounding up both real and unreal parts
string x1ip = Convert.ToString(Math.Round(x1.Imaginary, 5));
if (x1.Imaginary == 0)
{
Console.WriteLine(x1rp);
}
else if (x1.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x1rp + " - " + Math.Round(Complex.Abs(x1.Imaginary)) + "i");
}
else
{
Console.WriteLine(x1rp + " + " + x1ip + "i");
}
string x2rp = Convert.ToString(Math.Round(x2.Real, 5)); // rounding up both real and unreal parts
string x2ip = Convert.ToString(Math.Round(x2.Imaginary, 5));
if (x2.Imaginary == 0)
{
Console.WriteLine(x2rp);
}
else if (x2.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x2rp + " - " + Math.Round(Complex.Abs(x2.Imaginary)) + "i");
}
else
{
Console.WriteLine(x2rp + " + " + x2ip + "i");
}
string x3rp = Convert.ToString(Math.Round(x3.Real, 5)); // rounding up both real and unreal parts
string x3ip = Convert.ToString(Math.Round(x3.Imaginary, 5));
if (x3.Imaginary == 0)
{
Console.WriteLine(x3rp);
}
else if (x3.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x3rp + " - " + Math.Round(Complex.Abs(x3.Imaginary)) + "i");
}
else
{
Console.WriteLine(x3rp + " + " + x3ip + "i");
}
string x4rp = Convert.ToString(Math.Round(x4.Real, 5)); // rounding up both real and unreal parts
string x4ip = Convert.ToString(Math.Round(x4.Imaginary, 5));
if (x4.Imaginary == 0)
{
Console.WriteLine(x4rp);
}
else if (x4.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x4rp + " - " + Math.Round(Complex.Abs(x4.Imaginary)) + "i");
}
else
{
Console.WriteLine(x4rp + " + " + x4ip + "i");
}
// discriminant tests
if (discriminant == 0) // if delta = 0
{
if (P < 0 && D < 0 && deltazero != 0)
{
string result4 = "The equation yields a pair of double roots and two real simple roots.";
Console.WriteLine(result4);
}
else if (D > 0 || (P > 0 && (D != 0 || R != 0)))
{
string result5 = "The equation yields a pair of double roots and two complex conjugate roots.";
Console.WriteLine(result5);
}
else if (deltazero == 0 && D != 0)
{
string result6 = "The equation yields a triple root and a simple root.";
Console.WriteLine(result6);
}
else if (D == 0)
{
if (P < 0)
{
string result7 = "The equation yields two pairs of real double roots.";
Console.WriteLine(result7);
}
else if (P > 0 && R == 0)
{
string result8 = "The equation yields two pairs of double complex conjugate roots.";
Console.WriteLine(result8);
}
else if (deltazero == 0)
{
string result9pt2 = Convert.ToString(-(b / (4 * a)));
string result9 = "All of the roots of this equation are equal to -b/4a";
Console.WriteLine(result9 + "(" + result9pt2 + ")");
}
else
{
Console.WriteLine("ERROR");
}
}
else
{
Console.WriteLine("ERROR");
}
}
else if (discriminant > 0) // if delta > 0
{
if (P < 0 && D < 0)
{
string result2 = "The equation yields four distinct real roots.";
Console.WriteLine(result2);
}
else if (P > 0 && D > 0)
{
string result3 = "The equation yields two pairs of unreal complex conjugate roots.";
Console.WriteLine(result3);
}
else
{
Console.WriteLine("ERROR");
}
}
else if (discriminant < 0) // if delta < 0
{
string result1 = "The equation yields two distinct real roots and two complex conjugate non-real roots.";
Console.WriteLine(result1);
}
// discriminant of equation
Console.WriteLine(" ");
Console.WriteLine("Discriminant :");
Console.WriteLine(discriminant);
Console.ReadLine();
}
}
}
====================================== ==================
编辑#1:
我试过了 another method to solve the roots.
然而,虚部对于最后2根仍然是错误的。
如果有人能指出我的错误,我将不胜感激。
// different parts of the roots presented in p1-p6
double p = ((8 * a * c) - (3 * Math.Pow(b, 2))) / (8 * Math.Pow(a, 2));
double q = (Math.Pow(b, 3) - (4 * a * b * c) + (8 * Math.Pow(a, 2) * d)) / (8 * Math.Pow(a, 3));
double D0 = Math.Pow(c, 2) - (3 * b * d) + (12 * a * e);
double D1 = (2 * Math.Pow(c, 3)) - (9 * b * c * d) + (27 * Math.Pow(b, 2) * e) + (27 * a * Math.Pow(d, 2)) - (72 * a * c * e);
Complex Q = Complex.Pow((D1 + Complex.Sqrt(Complex.Pow(D1, 2) - (4 * Complex.Pow(D0, 3)))) / 2.0, 1.0 / 3.0);
Complex S = 1.0 / 2.0 * Complex.Sqrt((-2.0 / 3.0 * p) + (1.0 / (3 * a) * (Q + (D0 / Q))));
// calculating roots with p1-p6
Complex x1 = (-(b / 4 * a)) - S + (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
Complex x2 = (-(b / 4 * a)) - S - (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
Complex x3 = (-(b / 4 * a)) + S + (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
Complex x4 = (-(b / 4 * a)) + S - (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
====================================== ==================
编辑#2
问题已解决。
该程序现在能够求解四次方程。造成上述问题的原因其实是我在代码行中的小错别字
我从 here 得到了一个有效的算法。好像比你的简单。
double D0 = c * c - 3 * b * d + 12 * a * e;
double D1 = 2 * c * c * c - 9 * b * c * d + 27 * b * b * e + 27 * a * d * d - 72 * a * c * e;
double p = (8 * a * c - 3 * b * b) / (8 * a * a);
double q = (b * b * b - 4 * a * b * c + 8 * a * a * d) / (8 * a * a * a);
Complex Q = Complex.Pow((D1 + Complex.Sqrt(D1 * D1 - 4 * D0 * D0 * D0)) / 2, 1.0 / 3.0);
Complex S = Complex.Sqrt(-2 * p / 3 + (Q + D0 / Q) / (3 * a)) / 2;
Complex u = Complex.Sqrt(-4 * S * S - 2 * p + q / S) / 2;
Complex v = Complex.Sqrt(-4 * S * S - 2 * p - q / S) / 2;
Complex x1 = -b / (4 * a) - S + u;
Complex x2 = -b / (4 * a) - S - u;
Complex x3 = -b / (4 * a) + S + v;
Complex x4 = -b / (4 * a) + S - v;
此外,根据 this page,您可以使用这个代替非常长的判别式来获取其符号:
double discriminantSign = c * c - 3 * b * d + 12 * a * e;
我还注意到 4 个错别字,你在应用 Math.Round 函数时忘记提到小数点后 5 位,所以你的结果四舍五入为整数。
编辑:如果您的虚部仍有问题,那是因为您没有更正错别字:
Console.WriteLine(x1rp + " - " + Math.Round(Complex.Abs(x1.Imaginary)) + "i");
进入:
Console.WriteLine(x1rp + " - " + Math.Round(Complex.Abs(x1.Imaginary), 5) + "i");
除上述 4 行外,其他地方都保留 5 位小数。所以它正在四舍五入整数。全部替换。
这个帖子是我的
我和小伙伴正在尝试做一个可以自动计算的多功能计算器
二次、三次甚至四次方程的根。
但是,我们 运行 遇到了一些问题,以前是三次方程,现在是 四次方程。
与上一个主题不同,我们将提供图像,包括我们程序计算的答案和WolframAlpha计算的答案,而不是将它们放在此处的文本中。
四次方程将表示为
ax^4 + bx^3 + cx^2 + dx + e
Our method of finding the roots of a quartic equation. (在另一个网站的另一个线程中找到)
a=1 b=2 c=-41 d=-42 e=360
a=1 b=-0.25 c=-0.85 d=1.45 e=-4.35
a=1 b=2 c=3 d=4 e=5
如图所示,程序计算的判别式始终正确。但是,方程的根有时会导致错误 (NaN),并且根的性质也会导致错误,但与根一样频繁。
根据以上提供的所有信息,我们希望知道以下问题的答案:
- 究竟是什么导致了这些错误和问题,
- 我应该对我的代码进行什么修改,以便程序可以正常运行,
- 我们求四次方程根的方法是否正确,或者是否有可能通过一般的方法求所有四次方程的根公式,
- 最后但同样重要的是,有没有办法改进,或者压缩我们程序中的代码行,但仍然像我们一样运行打算这样做。
如前一帖所述,我们才刚刚开始学习C#。
为了您的方便,我们对一些代码行做了注释。
代码(C#):
using System;
using System.Numerics;
namespace ComplexNumbers
{
public class ComplexNo
{
public static void Main()
{
// prompting for coefficients and constant
Console.WriteLine("Quartic Equation Calculator :");
Console.Write("Insert first coefficient : ");
double a = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert second coefficient : ");
double b = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert third coefficient : ");
double c = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert fourth coefficient : ");
double d = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert constant : ");
double e = Convert.ToDouble(Console.ReadLine());
// discriminant
double discriminant = 256 * Math.Pow(a, 3) * Math.Pow(e, 3) - (192 * Math.Pow(a, 2) * b * d * Math.Pow(e, 2)) -
(128 * Math.Pow(a, 2) * Math.Pow(c, 2) * Math.Pow(e, 2)) + (144 * Math.Pow(a, 2) * c * Math.Pow(d, 2) * e) -
(27 * Math.Pow(a, 2) * Math.Pow(d, 4)) + (144 * a * Math.Pow(b, 2) * c * Math.Pow(e, 2)) -
(6 * a * Math.Pow(b, 2) * Math.Pow(d, 2) * e) - (80 * a * b * Math.Pow(c, 2) * d * e) +
(18 * a * b * c * Math.Pow(d, 3)) + (16 * a * Math.Pow(c, 4) * e) - (4 * a * Math.Pow(c, 3) * Math.Pow(d, 2)) -
(27 * Math.Pow(b, 4) * Math.Pow(e, 2)) + (18 * Math.Pow(b, 3) * c * d * e) -
(4 * Math.Pow(b, 3) * Math.Pow(d, 3)) - (4 * Math.Pow(b, 2) * Math.Pow(c, 3) * e) +
(Math.Pow(b, 2) * Math.Pow(c, 2) * Math.Pow(d, 2));
// different parts of the roots presented in p1-p6
double p1 = (2 * Math.Pow(c, 3)) - (9 * b * c * d) + (27 * a * Math.Pow(d, 2)) + (27 * Math.Pow(b, 2) * e) -
(72 * a * c * e);
double p2 = p1 + Math.Sqrt(-4.0 * Math.Pow(Math.Pow(c, 2) - (3 * b * d) + (12 * a * e), 3) + Math.Pow(p1, 2));
double p3 = ((Math.Pow(c, 2) - (3 * b * d) + (12 * a * e)) / (3 * a * Math.Cbrt(p2 / 2))) + (Math.Cbrt(p2 / 2) / (3 * a));
double p4 = Math.Sqrt((Math.Pow(b, 2) / (4 * Math.Pow(a, 2))) - (2 * c / (3 * a)) + p3);
double p5 = (Math.Pow(b, 2) / (2 * Math.Pow(a, 2))) - (4 * c / (3 * a)) - p3;
double p6 = ((-(Math.Pow(b, 3) / Math.Pow(a, 3))) + (4 * b * c / Math.Pow(a, 2)) - (8 * d / a)) / (4 * p4);
// calculating roots with p1-p6
Complex x1 = (-(b / (4 * a))) - (p4 / 2) - (Math.Sqrt(p5 - p6) / 2);
Complex x2 = (-(b / (4 * a))) - (p4 / 2) + (Math.Sqrt(p5 - p6) / 2);
Complex x3 = (-(b / (4 * a))) + (p4 / 2) - (Math.Sqrt(p5 - p6) / 2);
Complex x4 = (-(b / (4 * a))) + (p4 / 2) + (Math.Sqrt(p5 - p6) / 2);
// polynomials used for testing the nature of roots
double P = (8 * a * c) - (3 * Math.Pow(b, 2));
double R = Math.Pow(b, 3) + (8 * d * Math.Pow(a, 2)) - (4 * a * b * c);
double deltazero = Math.Pow(c, 2) - (3 * b * d) + (12 * a * e);
double D = (64 * Math.Pow(a, 3) * e) - (16 * Math.Pow(a, 2) * Math.Pow(c, 2)) +
(16 * a * Math.Pow(b, 2) * c) - (16 * Math.Pow(a, 2) * b * d) - (3 * Math.Pow(b, 4));
// results
Console.WriteLine(" ");
Console.WriteLine("Solve for " + a + "x^4 " + " + " + b + "x^3 " + " + " + c + "x^2 " + " + " + d + "x " + " + " + e + " :");
Console.WriteLine(" ");
Console.WriteLine("Results :");
Console.WriteLine("First Root :");
string x1rp = Convert.ToString(Math.Round(x1.Real, 5)); // rounding up both real and unreal parts
string x1ip = Convert.ToString(Math.Round(x1.Imaginary, 5));
if (x1.Imaginary == 0)
{
Console.WriteLine(x1rp);
}
else if (x1.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x1rp + " - " + Math.Round(Complex.Abs(x1.Imaginary)) + "i");
}
else
{
Console.WriteLine(x1rp + " + " + x1ip + "i");
}
string x2rp = Convert.ToString(Math.Round(x2.Real, 5)); // rounding up both real and unreal parts
string x2ip = Convert.ToString(Math.Round(x2.Imaginary, 5));
if (x2.Imaginary == 0)
{
Console.WriteLine(x2rp);
}
else if (x2.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x2rp + " - " + Math.Round(Complex.Abs(x2.Imaginary)) + "i");
}
else
{
Console.WriteLine(x2rp + " + " + x2ip + "i");
}
string x3rp = Convert.ToString(Math.Round(x3.Real, 5)); // rounding up both real and unreal parts
string x3ip = Convert.ToString(Math.Round(x3.Imaginary, 5));
if (x3.Imaginary == 0)
{
Console.WriteLine(x3rp);
}
else if (x3.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x3rp + " - " + Math.Round(Complex.Abs(x3.Imaginary)) + "i");
}
else
{
Console.WriteLine(x3rp + " + " + x3ip + "i");
}
string x4rp = Convert.ToString(Math.Round(x4.Real, 5)); // rounding up both real and unreal parts
string x4ip = Convert.ToString(Math.Round(x4.Imaginary, 5));
if (x4.Imaginary == 0)
{
Console.WriteLine(x4rp);
}
else if (x4.Imaginary < 0) // testing if unreal part is negative
{
Console.WriteLine(x4rp + " - " + Math.Round(Complex.Abs(x4.Imaginary)) + "i");
}
else
{
Console.WriteLine(x4rp + " + " + x4ip + "i");
}
// discriminant tests
if (discriminant == 0) // if delta = 0
{
if (P < 0 && D < 0 && deltazero != 0)
{
string result4 = "The equation yields a pair of double roots and two real simple roots.";
Console.WriteLine(result4);
}
else if (D > 0 || (P > 0 && (D != 0 || R != 0)))
{
string result5 = "The equation yields a pair of double roots and two complex conjugate roots.";
Console.WriteLine(result5);
}
else if (deltazero == 0 && D != 0)
{
string result6 = "The equation yields a triple root and a simple root.";
Console.WriteLine(result6);
}
else if (D == 0)
{
if (P < 0)
{
string result7 = "The equation yields two pairs of real double roots.";
Console.WriteLine(result7);
}
else if (P > 0 && R == 0)
{
string result8 = "The equation yields two pairs of double complex conjugate roots.";
Console.WriteLine(result8);
}
else if (deltazero == 0)
{
string result9pt2 = Convert.ToString(-(b / (4 * a)));
string result9 = "All of the roots of this equation are equal to -b/4a";
Console.WriteLine(result9 + "(" + result9pt2 + ")");
}
else
{
Console.WriteLine("ERROR");
}
}
else
{
Console.WriteLine("ERROR");
}
}
else if (discriminant > 0) // if delta > 0
{
if (P < 0 && D < 0)
{
string result2 = "The equation yields four distinct real roots.";
Console.WriteLine(result2);
}
else if (P > 0 && D > 0)
{
string result3 = "The equation yields two pairs of unreal complex conjugate roots.";
Console.WriteLine(result3);
}
else
{
Console.WriteLine("ERROR");
}
}
else if (discriminant < 0) // if delta < 0
{
string result1 = "The equation yields two distinct real roots and two complex conjugate non-real roots.";
Console.WriteLine(result1);
}
// discriminant of equation
Console.WriteLine(" ");
Console.WriteLine("Discriminant :");
Console.WriteLine(discriminant);
Console.ReadLine();
}
}
}
====================================== ==================
编辑#1:
我试过了 another method to solve the roots.
然而,虚部对于最后2根仍然是错误的。
如果有人能指出我的错误,我将不胜感激。
// different parts of the roots presented in p1-p6
double p = ((8 * a * c) - (3 * Math.Pow(b, 2))) / (8 * Math.Pow(a, 2));
double q = (Math.Pow(b, 3) - (4 * a * b * c) + (8 * Math.Pow(a, 2) * d)) / (8 * Math.Pow(a, 3));
double D0 = Math.Pow(c, 2) - (3 * b * d) + (12 * a * e);
double D1 = (2 * Math.Pow(c, 3)) - (9 * b * c * d) + (27 * Math.Pow(b, 2) * e) + (27 * a * Math.Pow(d, 2)) - (72 * a * c * e);
Complex Q = Complex.Pow((D1 + Complex.Sqrt(Complex.Pow(D1, 2) - (4 * Complex.Pow(D0, 3)))) / 2.0, 1.0 / 3.0);
Complex S = 1.0 / 2.0 * Complex.Sqrt((-2.0 / 3.0 * p) + (1.0 / (3 * a) * (Q + (D0 / Q))));
// calculating roots with p1-p6
Complex x1 = (-(b / 4 * a)) - S + (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
Complex x2 = (-(b / 4 * a)) - S - (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
Complex x3 = (-(b / 4 * a)) + S + (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
Complex x4 = (-(b / 4 * a)) + S - (1.0 / 2.0 * Complex.Sqrt((-4.0 * Complex.Pow(S, 2)) - (2 * p) + (q / S)));
====================================== ==================
编辑#2
问题已解决。
该程序现在能够求解四次方程。造成上述问题的原因其实是我在代码行中的小错别字
我从 here 得到了一个有效的算法。好像比你的简单。
double D0 = c * c - 3 * b * d + 12 * a * e;
double D1 = 2 * c * c * c - 9 * b * c * d + 27 * b * b * e + 27 * a * d * d - 72 * a * c * e;
double p = (8 * a * c - 3 * b * b) / (8 * a * a);
double q = (b * b * b - 4 * a * b * c + 8 * a * a * d) / (8 * a * a * a);
Complex Q = Complex.Pow((D1 + Complex.Sqrt(D1 * D1 - 4 * D0 * D0 * D0)) / 2, 1.0 / 3.0);
Complex S = Complex.Sqrt(-2 * p / 3 + (Q + D0 / Q) / (3 * a)) / 2;
Complex u = Complex.Sqrt(-4 * S * S - 2 * p + q / S) / 2;
Complex v = Complex.Sqrt(-4 * S * S - 2 * p - q / S) / 2;
Complex x1 = -b / (4 * a) - S + u;
Complex x2 = -b / (4 * a) - S - u;
Complex x3 = -b / (4 * a) + S + v;
Complex x4 = -b / (4 * a) + S - v;
此外,根据 this page,您可以使用这个代替非常长的判别式来获取其符号:
double discriminantSign = c * c - 3 * b * d + 12 * a * e;
我还注意到 4 个错别字,你在应用 Math.Round 函数时忘记提到小数点后 5 位,所以你的结果四舍五入为整数。
编辑:如果您的虚部仍有问题,那是因为您没有更正错别字:
Console.WriteLine(x1rp + " - " + Math.Round(Complex.Abs(x1.Imaginary)) + "i");
进入:
Console.WriteLine(x1rp + " - " + Math.Round(Complex.Abs(x1.Imaginary), 5) + "i");
除上述 4 行外,其他地方都保留 5 位小数。所以它正在四舍五入整数。全部替换。