Beispiel #1
0
        public static double[] Solve(double c, double d)
        {
            if (d < 0)
            {
                return(Solve(c, -d).Reverse().Select(x => - x).ToArray());
            }

            // 最小の実数解
            var x1 = d == 0 && c >= 0 ? 0 : SolveNegative();

            // f(x) = (x - x_1) (x^2 + x_1 x + x_1^2 + c)
            var det = -3 * x1 * x1 - 4 * c;

            if (det < 0)
            {
                return new[] { x1 }
            }
            ;
            return(new[] { x1, (-x1 - Sqrt(det)) / 2, (-x1 + Sqrt(det)) / 2 });

            double SolveNegative()
            {
                var f = CubicEquation1.CreateFunction(c, d);

                var f1 = CubicEquation1.CreateDerivative(c);
                var x0 = -1D;

                while (f(x0) > 0)
                {
                    x0 *= 2;
                }
                return(NewtonMethod.Solve(f, f1, x0));
            }
        }
    }
        public void Solve_2_2()
        {
            Test(0, 2);
            Test(0, -100);
            Test(3, 0);
            Test(1, 1);
            Test(10, -10);
            Test(-7, 0);
            Test(-10, 127);
            Test(-1, -10);
            Test(-100, 90);
            Test(-15, -4);
            Test(-1.5, Math.Sqrt(2) / 2);
            Test(-6 * Math.Pow(2, 1 / 3.0), -8);

            void Test(double c, double d)
            {
                var actual = target2(c, d);
                var det    = (-4 * c * c * c - 27 * d * d).RoundAlmost();

                Assert.AreEqual(c == 0 & d == 0 || det < 0 ? 1 : det == 0 ? 2 : 3, actual.Length);

                var f = CubicEquation1.CreateFunction(c, d);

                foreach (var x in actual)
                {
                    Assert2.AreNearlyEqual(0, f(x));
                }
            }
        }
        public void Solve_2_1()
        {
            Test(new[] { 0.0 }, 0, 0);
            Test(new[] { -1.0 }, 0, 1);
            Test(new[] { 2.0 }, 0, -8);
            Test(new[] { 0.0 }, 1, 0);
            Test(new[] { -2.0 }, 2, 12);
            Test(new[] { 1.0 }, 1, -2);
            Test(new[] { -3.0, 0.0, 3.0 }, -9, 0);
            Test(new[] { -3.0 }, -5, 12);
            Test(new[] { 5.0 }, -7, -90);
            Test(new[] { -4.0, 2.0 }, -12, 16);
            Test(new[] { -1.5, 3.0 }, -6.75, -6.75);
            Test(new[] { -3.0, 1.0, 2.0 }, -7, 6);
            Test(new[] { -7.0, -5.0, 12.0 }, -109, -420);

            void Test(double[] expected, double c, double d)
            {
                var actual = target2(c, d);

                CollectionAssert.AreEqual(expected, actual);

                var f = CubicEquation1.CreateFunction(c, d);

                foreach (var x in actual)
                {
                    Assert2.AreNearlyEqual(0, f(x));
                }
            }
        }
        public void Solve_1_2()
        {
            Test(3, 3, 3);
            Test(1, 0, 1);
            Test(1, -1, 0);
            Test(3, -2, -6);

            void Test(double b, double c, double d)
            {
                var actual = target1(b, c, d);

                var f = CubicEquation1.CreateFunction(1, b, c, d);

                foreach (var x in actual)
                {
                    Assert2.AreNearlyEqual(0, f(x));
                }
            }
        }
        public void Solve_1_1()
        {
            Test(new[] { 0.0 }, 1, 1, 0);
            Test(new[] { -2.0 }, 3, 4, 4);
            Test(new[] { -2.0 }, 1, -1, 2);
            Test(new[] { -3.0, 1.0 }, 1, -5, 3);

            void Test(double[] expected, double b, double c, double d)
            {
                var actual = target1(b, c, d);

                actual = Array.ConvertAll(actual, x => x.RoundAlmost());
                CollectionAssert.AreEqual(expected, actual);

                var f = CubicEquation1.CreateFunction(1, b, c, d);

                foreach (var x in actual)
                {
                    Assert2.AreNearlyEqual(0, f(x));
                }
            }
        }