最近我和朋友決定做一個多功能計算器來自動求二次方程的根。畢竟這并沒有那么具有挑戰性,所以我們決定更上一層樓,為三次方程制作一個計算器。
(ax^3 bx^2 cx d)
然而,我們偶然發現了一些瑣碎的問題,無論我們如何努力,結果仍然是一樣的。我們在編碼方面是初學者,所以我們不確定我們是否真的在這里犯了一些愚蠢的錯誤,但至少我們想從別人那里學到一些東西。
基本上,我們已經嘗試了很多不同三次方程的組合,甚至重新編碼整個事情。問題是我們產生的結果總是錯誤的,但僅限于第二根和第三根的實部。
為了更好地理解,我們以9x^3 8x^2 7x 6為例進行了嘗試。
根據三次方程計算器網站,正確答案是
(網站)
第一根= -0.87285
第二根= -0.00802 0.87391 i
第三根= -0.00802 - 0.87391 i
然而,我們對這個等式的結果是:
第一根= -0.87285
第二根= -0.2963 0.87391 i
第三根= -0.2963 -0.87391 i
很明顯,只有第二和第三根的部分是錯誤的。
我們已經嘗試尋找類似的執行緒來提供幫助,但是這些對于我們來說有點難以理解,或者這些問題與我們的不同。
我們期待找到解決這個問題的方法和原因。
我們將求三次方程根的公式分為 5 個部分。
(rootp1-rootp5)
公式根據中文版維基百科的三次方程頁面中可以找到的公式進行編碼。
(公式)
我們還將根的實部四舍五入為 5 位數。
(有些代碼行可能是多余的,但正如我所提到的,我們是編碼新手)
代碼(C#):
using System;
using System.Numerics;
namespace ComplexNumbers
{
public class ComplexNo
{
public static void Main()
{
Console.WriteLine("Cubic 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 constant : ");
double d = Convert.ToDouble(Console.ReadLine());
Console.WriteLine(" ");
Console.WriteLine("Solve for " a "x" "^3 " b "x^2 " c "x " d " :");
double rootp1 = -(b / (3 * a));
double rootp2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double rootp3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
Complex root1 = rootp1 Math.Cbrt(rootp2 Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3)))
Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3)));
Complex rootp4 = new Complex(-1 / 2, Math.Sqrt(3) / 2);
Complex rootp5 = new Complex(-1 / 2, -(Math.Sqrt(3) / 2));
Complex root2 = rootp1 (rootp4 * Math.Cbrt(rootp2 Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3))))
(rootp5 * Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3))));
Complex root3 = rootp1 (rootp5 * Math.Cbrt(rootp2 Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3))))
(rootp4 * Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3))));
Console.WriteLine(" ");
Console.WriteLine("Results :");
Console.WriteLine("First Root :");
string root1rp = Convert.ToString(Math.Round(root1.Real, 5));
string root1ip = Convert.ToString(Math.Round(root1.Imaginary, 5));
Console.WriteLine(root1rp " " root1ip "i");
Console.WriteLine("Second Root :");
string root2rp = Convert.ToString(Math.Round(root2.Real, 5));
string root2ip = Convert.ToString(Math.Round(root2.Imaginary, 5));
Console.WriteLine(root2rp " " root2ip "i");
Console.WriteLine("Third Root :");
string root3rp = Convert.ToString(Math.Round(root3.Real, 5));
string root3ip = Convert.ToString(Math.Round(root3.Imaginary, 5));
Console.WriteLine(root3rp " " root3ip "i");
Console.ReadLine();
}
}
}
(抱歉讓這個執行緒這么長而且我的語法不好)
uj5u.com熱心網友回復:
問題出在這條線上Complex rootp4 = new Complex(-1 / 2, Math.Sqrt(3) / 2);。 -1/2使用整數除法并計算為 0。
此代碼將起作用。
Console.WriteLine(" ");
Console.WriteLine("Solve for " a "x" "^3 " b "x^2 " c "x " d " :");
double minusBover3a = -(b / (3 * a));
double rootp2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double rootp3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
double bigCubeRootPlus = Math.Cbrt(rootp2 Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3)));
double bigCubeRootMinus = Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) Math.Pow(rootp3, 3)));
// ** THIS IS THE PROBLEM. "-1/2" uses integer division, so this complex has 0 for real part
Complex complexPlus = new Complex(-1.0 / 2, Math.Sqrt(3) / 2);
Complex complexMinus = new Complex(-1.0 / 2, -(Math.Sqrt(3) / 2));
Complex root1 = minusBover3a bigCubeRootPlus bigCubeRootMinus;
Complex root2 = minusBover3a complexPlus * bigCubeRootPlus complexMinus * bigCubeRootMinus;
Complex root3 = minusBover3a complexMinus * bigCubeRootPlus complexPlus * bigCubeRootMinus;
uj5u.com熱心網友回復:
我承認我沒有嘗試過您的代碼,但是您的原始計算中的數學可能存在鑄造問題。試試這個:
double rootp2 = ((double)b * (double)c / (6D * Math.Pow(a, 2D))) - (Math.Pow(b, 3D) / (27D * Math.Pow(a, 3D))) - ((double)d / (2D * (double)a));
如果這有所不同,您必須通過其他計算傳播類似的更改(將所有變數轉換為(double)和行內常量作為 double with )。D
uj5u.com熱心網友回復:
以下是您的代碼的替代方法:
// from https://www.daniweb.com/programming/software-development/
// code/454493/solving-the-cubic-equation-using-the-complex-struct
// algorithm described in
// https://en.wikipedia.org/wiki/Cubic_equation#General_cubic_formula
const int NRoots = 3;
double SquareRootof3 = Math.Sqrt(3);
// the 3 cubic roots of 1
var CubicUnity = new List<Complex>(NRoots)
{ new Complex(1, 0),
new Complex(-0.5, -SquareRootof3 / 2.0),
new Complex(-0.5, SquareRootof3 / 2.0) };
// intermediate calculations
double DELTA = 18 * a * b * c * d
- 4 * b * b * b * d
b * b * c * c
- 4 * a * c * c * c
- 27 * a * a * d * d;
double DELTA0 = b * b - 3 * a * c;
double DELTA1 = 2 * b * b * b
- 9 * a * b * c
27 * a * a * d;
Complex DELTA2 = -27 * a * a * DELTA;
Complex C = Complex.Pow((DELTA1 Complex.Pow(DELTA2, 0.5)) / 2, 1 / 3.0);
for (int i = 0; i < NRoots; i )
{
Complex M = CubicUnity[i] * C;
Complex Root = -1.0 / (3 * a) * (b M DELTA0 / M);
Console.WriteLine();
Console.WriteLine($"Root {i 1}:");
Console.WriteLine($"Real {Root.Real:0.#####}");
Console.WriteLine($"Imaginary {Root.Imaginary:0.#####}i");
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/424835.html
