/// <summary> /// output string represents "c1x + c0" /// </summary> public static string PolynomialToString(WWComplex c1, WWComplex c0, string variableSymbol) { if (c1.Magnitude() == 0) { return(string.Format("{0}", c0)); } return(string.Format("{0}{1}", FirstCoeffToString(c1, variableSymbol), ZeroOrderCoeffToString(c0))); }
/// <summary> /// rational poly /// n1x + n0 /// ---------- /// d1x + d0 /// </summary> /// <param name="n1">numerator first orderPlus1 coefficient</param> /// <param name="n0">numerator zero orderPlus1 coefficient</param> /// <param name="d1">denominator first orderPlus1 coefficient</param> /// <param name="d0">denominator zero orderPlus1 coefficient</param> public FirstOrderComplexRationalPolynomial(WWComplex n1, WWComplex n0, WWComplex d1, WWComplex d0) { if (d1.Magnitude() == 0 && d0.Magnitude() == 0) { throw new DivideByZeroException(); } numer[1] = n1; numer[0] = n0; denom[1] = d1; denom[0] = d0; }
/// <summary> /// 1乗以上の項が存在するときに、そのあとにつなげて書くときの定数項の値表示。 /// </summary> public static string ZeroOrderCoeffToString(WWComplex c) { if (c.Magnitude() == 0) { return(""); } if (c.imaginary == 0) { if (c.real < 0) { return(string.Format(" {0}", c.real)); } else { return(string.Format(" +{0}", c.real)); } } if (c.real == 0) { if (c.imaginary == 1) { return(string.Format(" {0}", WWComplex.imaginaryUnit)); } if (c.imaginary == -1) { return(string.Format(" -{0}", WWComplex.imaginaryUnit)); } if (c.imaginary < 0) { return(string.Format(" {0}{1}", c.imaginary, WWComplex.imaginaryUnit)); } else { return(string.Format(" +{0}{1}", c.imaginary, WWComplex.imaginaryUnit)); } } if (c.real < 0) { return(c.ToString()); } else { return(string.Format(" +{0}", c)); } }
/// <summary> /// output string represents "c2x^2 + c1x + c0" /// </summary> public static string PolynomialToString(WWComplex c2, WWComplex c1, WWComplex c0, string variableSymbol) { if (c2.Magnitude() == 0) { // 1乗以下の項のみ。 return(PolynomialToString(c1, c0, variableSymbol)); } if (c1.Magnitude() == 0 && c0.Magnitude() == 0) { // 2乗の項のみ。 return(FirstCoeffToString(c2, string.Format("{0}^2", variableSymbol))); } if (c0.Magnitude() == 0) { // 2乗の項と1乗の項。 return(string.Format("{0}{1}", FirstCoeffToString(c2, string.Format("{0}^2", variableSymbol)), ContinuedCoeffToString(c1, variableSymbol))); } if (c1.Magnitude() == 0) { // 2乗の項と定数項。 return(string.Format("{0}{1}", FirstCoeffToString(c2, string.Format("{0}^2", variableSymbol)), ZeroOrderCoeffToString(c0))); } // 2乗+1乗+定数 return(string.Format("{0}{1}{2}", FirstCoeffToString(c2, string.Format("{0}^2", variableSymbol)), ContinuedCoeffToString(c1, variableSymbol), ZeroOrderCoeffToString(c0))); }
private void FindRootCubic(double[] coeffs) { // 3次多項式 cubic poly equation // https://en.wikipedia.org/wiki/Cubic_function#Algebraic_solution System.Diagnostics.Debug.Assert(4 == coeffs.Length); double a = coeffs[3]; double b = coeffs[2]; double c = coeffs[1]; double d = coeffs[0]; double Δ = 18 * a * b * c * d - 4 * b * b * b * d + 1 * b * b * c * c - 4 * a * c * c * c - 27 * a * a * d * d; double Δ0 = b * b - 3 * a * c; // ↓ 雑な0かどうかの判定処理。 if (AlmostZero(Δ)) { if (AlmostZero(Δ0)) { // triple root double root = -b / (3 * a); mRoots.Add(new WWComplex(root, 0)); mRoots.Add(new WWComplex(root, 0)); mRoots.Add(new WWComplex(root, 0)); return; } // double root and a simple root double root2 = (9 * a * d - b * c) / (2 * Δ0); double root1 = (4 * a * b * c - 9 * a * a * d - b * b * b); mRoots.Add(new WWComplex(root2, 0)); mRoots.Add(new WWComplex(root2, 0)); mRoots.Add(new WWComplex(root1, 0)); return; } { double Δ1 = +2 * b * b * b - 9 * a * b * c + 27 * a * a * d; WWComplex C; { WWComplex c1 = new WWComplex(Δ1 / 2, 0); double c2Sqrt = Math.Sqrt(Math.Abs(-27 * a * a * Δ) / 4); WWComplex c2; if (Δ < 0) { //C2 is real number c2 = new WWComplex(c2Sqrt, 0); } else { //C2 is imaginary number c2 = new WWComplex(0, c2Sqrt); } WWComplex c1c2; WWComplex c1Pc2 = WWComplex.Add(c1, c2); WWComplex c1Mc2 = WWComplex.Sub(c1, c2); if (c1Mc2.Magnitude() <= c1Pc2.Magnitude()) { c1c2 = c1Pc2; } else { c1c2 = c1Mc2; } // 3乗根 = 大きさが3分の1乗で角度が3分の1. double magnitude = c1c2.Magnitude(); double phase = c1c2.Phase(); double cMag = Math.Pow(magnitude, 1.0 / 3.0); double cPhase = phase / 3; C = new WWComplex(cMag * Math.Cos(cPhase), cMag * Math.Sin(cPhase)); } var ζ = new WWComplex(-1.0 / 2.0, 1.0 / 2.0 * Math.Sqrt(3.0)); var ζ2 = new WWComplex(-1.0 / 2.0, -1.0 / 2.0 * Math.Sqrt(3.0)); var r3a = new WWComplex(-1.0 / 3.0 / a, 0); WWComplex root0 = WWComplex.Mul(r3a, WWComplex.Add( WWComplex.Add(new WWComplex(b, 0), C), WWComplex.Div(new WWComplex(Δ0, 0), C))); WWComplex root1 = WWComplex.Mul(r3a, WWComplex.Add( WWComplex.Add(new WWComplex(b, 0), WWComplex.Mul(ζ, C)), WWComplex.Div(new WWComplex(Δ0, 0), WWComplex.Mul(ζ, C)))); WWComplex root2 = WWComplex.Mul(r3a, WWComplex.Add( WWComplex.Add(new WWComplex(b, 0), WWComplex.Mul(ζ2, C)), WWComplex.Div(new WWComplex(Δ0, 0), WWComplex.Mul(ζ2, C)))); mRoots.Add(root0); mRoots.Add(root1); mRoots.Add(root2); return; } }