Пример #1
0
        /// <summary>
        ///     Solves the equation \f$e + d x + c x^2 + b x^3 + a x^4 = 0\f$, returning all real values of
        ///		\f$x\f$ for which the equation is true. See https://en.wikipedia.org/wiki/Quartic_function for the
        ///		algorithm used.
        /// </summary>
        public static IEnumerable <float> Solve(float e2, float d2, float c2, float b2, float a2)
        {
            if (Math.Abs(a2) <= 0.005f)
            {
                foreach (float v in CubicFunction.Solve(e2, d2, c2, b2))
                {
                    yield return(v);
                }
                yield break;
            }

            double a = a2;
            double b = b2;
            double c = c2;
            double d = d2;
            double e = e2;

            double ba = b / a;
            double ca = c / a;
            double da = d / a;
            double ea = e / a;

            double p1 = c * c * c - 4.5 * b * c * d + 13.5 * a * d * d + 13.5 * b * b * e - 36.0 * a * c * e;

            double q = c * c - 3.0 * b * d + 12.0 * a * e;

            Complex p2 = p1 + Complex.Sqrt(-q * q * q + p1 * p1);

            Complex pow = Complex.Pow(p2, (1.0 / 3.0));

            Complex p3 = q / (3.0 * a * pow) + pow / (3.0 * a);

            Complex p4 = Complex.Sqrt(ba * ba / 4.0 - 2.0 * ca / (3.0) + p3);

            Complex p5 = b * b / (2.0 * a * a) - 4.0 * c / (3.0 * a) - p3;

            Complex p6 = (-ba * ba * ba + 4.0 * ba * ca - 8.0 * da) / (4.0 * p4);

            List <Complex> roots = new List <Complex>
            {
                -ba / (4.0) - p4 / 2.0 - 0.5 * Complex.Sqrt(p5 - p6),
                -ba / (4.0) - p4 / 2.0 + 0.5 * Complex.Sqrt(p5 - p6),
                -ba / (4.0) + p4 / 2.0 - 0.5 * Complex.Sqrt(p5 + p6),
                -ba / (4.0) + p4 / 2.0 + 0.5 * Complex.Sqrt(p5 + p6),
            };

            foreach (Complex root in roots)
            {
                if (Math.Abs(root.Imaginary) <= 0.005f)
                {
                    yield return((float)root.Real);
                }
            }
        }
Пример #2
0
        /// <summary>
        ///     Solves the equation \f$a0 + a1 x + a2 x^2 + a3 x^3 + a4 x^4 = 0\f$, returning all real values of
        ///		\f$x\f$ for which the equation is true. See https://en.wikipedia.org/wiki/Quartic_function for the
        ///		algorithm used.
        /// </summary>
        public static IEnumerable <double> Solve(double a0, double a1, double a2, double a3, double a4)
        {
            DebugUtil.AssertAllFinite(new double[] { a0, a1, a2, a3, a4 }, "a");
            if (Math.Abs(a4) <= 0.005)
            {
                foreach (double v in CubicFunction.Solve(a0, a1, a2, a3))
                {
                    QuarticFunction f = new QuarticFunction(a0, a1, a2, a3, a4);
                    yield return(f.NewtonRaphson(v));
                }
                yield break;
            }

            double ba = a3 / a4;
            double ca = a2 / a4;
            double da = a1 / a4;
            // double ea = a0/a4;

            double p1 = a2 * a2 * a2 - 4.5 * a3 * a2 * a1 + 13.5 * a4 * a1 * a1 + 13.5 * a3 * a3 * a0 - 36.0 * a4 * a2 * a0;

            double q = a2 * a2 - 3.0 * a3 * a1 + 12.0 * a4 * a0;

            Complex p2 = p1 + Complex.Sqrt(-q * q * q + p1 * p1);

            Complex pow = Complex.Pow(p2, (1.0 / 3.0));

            Complex p3 = q / (3.0 * a4 * pow) + pow / (3.0 * a4);

            Complex p4 = Complex.Sqrt(ba * ba / 4.0 - 2.0 * ca / (3.0) + p3);

            Complex p5 = a3 * a3 / (2.0 * a4 * a4) - 4.0 * a2 / (3.0 * a4) - p3;

            Complex p6 = (-ba * ba * ba + 4.0 * ba * ca - 8.0 * da) / (4.0 * p4);

            List <Complex> roots = new List <Complex>
            {
                -ba / (4.0) - p4 / 2.0 - 0.5 * Complex.Sqrt(p5 - p6),
                -ba / (4.0) - p4 / 2.0 + 0.5 * Complex.Sqrt(p5 - p6),
                -ba / (4.0) + p4 / 2.0 - 0.5 * Complex.Sqrt(p5 + p6),
                -ba / (4.0) + p4 / 2.0 + 0.5 * Complex.Sqrt(p5 + p6),
            };

            foreach (Complex root in roots)
            {
                if (Math.Abs(root.Imaginary) <= 0.005)
                {
                    DebugUtil.AssertFinite(root.Real, nameof(root.Real));
                    yield return(root.Real);
                }
            }
        }
Пример #3
0
        /// <summary>
        ///     Solves the equation \f$a0 + a1 x + a2 x^2 + a3 x^3 = 0\f$, returning all real values of
        ///		\f$x\f$ for which the equation is true. See https://en.wikipedia.org/wiki/Cubic_equation for the
        ///		algorithm used.
        /// </summary>
        public static IEnumerable <double> Solve(double a0, double a1, double a2, double a3)
        {
            DebugUtil.AssertFinite(a3, nameof(a3));
            DebugUtil.AssertFinite(a2, nameof(a2));
            DebugUtil.AssertFinite(a1, nameof(a1));
            DebugUtil.AssertFinite(a0, nameof(a0));
            if (Math.Abs(a3) <= 0.005)
            {
                foreach (double v in QuadraticFunction.Solve(a0, a1, a2))
                {
                    CubicFunction f = new CubicFunction(a0, a1, a2, a3);
                    yield return(f.NewtonRaphson(v));
                }
                yield break;
            }

            double delta0 = a2 * a2 - 3.0 * a3 * a1;
            double delta1 = 2.0 * a2 * a2 * a2 - 9.0 * a3 * a2 * a1 + 27.0 * a3 * a3 * a0;

            Complex p1 = Complex.Sqrt(delta1 * delta1 - 4.0 * delta0 * delta0 * delta0);

            // The sign we choose in the next equation is arbitrary. To prevent a divide-by-zero down the line, if p2 is
            // zero, we must choose the opposite sign to make it nonzero:
            Complex p2 = delta1 + p1;

            Complex c = Complex.Pow(0.5 * p2, (1.0 / 3.0));

            Complex xi = -0.5 + 0.5 * Complex.Sqrt(-3.0);

            List <Complex> roots = new List <Complex>
            {
                -1.0 / (3.0 * a3) * (a2 + c + delta0 / c),
                -1.0 / (3.0 * a3) * (a2 + xi * c + delta0 / (xi * c)),
                -1.0 / (3.0 * a3) * (a2 + xi * xi * c + delta0 / (xi * xi * c)),
            };

            foreach (Complex root in roots)
            {
                if (Math.Abs(root.Imaginary) <= 0.05)
                {
                    DebugUtil.AssertFinite(root.Real, nameof(root.Real));
                    yield return(root.Real);
                }
            }
        }
Пример #4
0
 public IEnumerable <float> Roots()
 {
     return(CubicFunction.Solve(a0, a1, a2, a3));
 }