예제 #1
0
        private (int time, bool hasSpecialCharacter) ParseCalculationPattern(Time time, string calculationPattern)
        {
            var splittedPattern = calculationPattern.Split(':');

            if (splittedPattern.Length != 2)
            {
                throw new FormatException("Calculation format. Expected [S].");
            }

            var timePattern  = splittedPattern.FirstOrDefault();
            int concreteTime = GetTimeFromTimePattern(time, timePattern);

            var formulaPattern = splittedPattern.LastOrDefault();

            IFormulaExecutor formula = new FormulaExecutor();

            (int formulaResult, int formulaValue, string specialCharacter) = formula.Execute(concreteTime, formulaPattern);

            if (specialCharacter == null)
            {
                SubtractTime(time, formulaValue * formulaResult, timePattern);
            }

            return(formulaResult, specialCharacter != null);
        }
예제 #2
0
        public double Integration(FormulaExecutor integrand, double a, double b, double eps)
        {
            //заменим особые предельные точки на точки из окрестности
            if (Double.IsNaN(integrand.Execute(a)) || Double.IsInfinity(integrand.Execute(a)))
            {
                a += 0.0001 * eps * (b - a);
            }
            if (Double.IsNaN(integrand.Execute(b)) || Double.IsInfinity(integrand.Execute(b)))
            {
                b -= 0.0001 * eps * (b - a);
            }
            //последовательно посчитаем производные до 4 порядка на 100 точках
            int n = 1000;

            //первая производная
            double[] deriv = new double[n];
            deriv[0] = (integrand.Execute(a + (b - a) / (n - 1)) - integrand.Execute(a)) / ((b - a) / (n - 1));
            for (int i = 1; i < n; ++i)
            {
                deriv[i] = (integrand.Execute(a + i * (b - a) / (n - 1)) - integrand.Execute(a + (i - 1) * (b - a) / (n - 1))) / ((b - a) / (n - 1));
            }
            //вторая производная
            double[] secDeriv = new double[n];
            secDeriv[0] = (deriv[1] - deriv[0]) / ((b - a) / (n - 1));
            for (int i = 1; i < n; ++i)
            {
                secDeriv[i] = (deriv[i] - deriv[i - 1]) / ((b - a) / (n - 1));
            }
            //третья производная
            double[] thirdDeriv = new double[n];
            thirdDeriv[0] = (secDeriv[1] - secDeriv[0]) / ((b - a) / (n - 1));
            for (int i = 1; i < n; ++i)
            {
                thirdDeriv[i] = (secDeriv[i] - secDeriv[i - 1]) / ((b - a) / (n - 1));
            }
            //четвертая производная
            double[] fourthDeriv = new double[n];
            fourthDeriv[0] = (thirdDeriv[1] - thirdDeriv[0]) / ((b - a) / (n - 1));
            double maxFourthDeriv = Math.Abs(fourthDeriv[0]);

            for (int i = 1; i < n; ++i)
            {
                fourthDeriv[i] = (thirdDeriv[i] - thirdDeriv[i - 1]) / ((b - a) / (n - 1));
                if (Math.Abs(fourthDeriv[i]) > maxFourthDeriv)
                {
                    maxFourthDeriv = Math.Abs(fourthDeriv[i]);
                }
            }
            //определим шаг разбиения h для метода
            double h = (b - a) / Math.Ceiling(Math.Pow(maxFourthDeriv * Math.Pow(b - a, 5) / (2880 * eps), 0.25));
            //найдем значение интеграла
            double sum = 0;

            for (int i = 0; i *h < (b - a); ++i)
            {
                sum += h / 6 * (integrand.Execute(a + i * h) + 4 * integrand.Execute(a + i * h + h / 2) + integrand.Execute(a + (i + 1) * h));
            }
            return(sum);
        }
예제 #3
0
        private void button1_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "";
            Parser parserComp = new Parser();
            //при помощи компонента-парсера преобразуем входные данные
            //в формат, используемый другими компонентами:
            //считаем пределы интегрирования и погрешность
            double a = 0, b = 0, eps = 0;

            if (!parserComp.ParseParam(ref a, ref b, ref eps, textBox2.Text, textBox3.Text, textBox4.Text))
            {
                richTextBox1.Text += "Ошибка ввода параметров";
                return;
            }
            parserComp.Dispose();
            //преобразуем строку в очередь токенов в обратной польской нотации
            //для компонента, вычисляющего значения формулы при подстановке
            FormulaExecutor formulaComp = new FormulaExecutor(parserComp.ShuntingYard(textBox1.Text));

            if (formulaComp.formula == null)
            {
                richTextBox1.Text += "Ошибка ввода выражения";
                return;
            }
            //при помощи компонентов методов численного интегрирования вычислим значение опред. интеграла
            Container methodComponents = new Container();

            if (checkBox1.Checked)
            {
                RectangleMethod rectangleComp = new RectangleMethod();
                methodComponents.Add(rectangleComp);
                richTextBox1.Text += (rectangleComp.Integration(formulaComp, a, b, eps).ToString()
                                      + " (метод левых прямоугольников)\n");
            }
            if (checkBox2.Checked)
            {
                TrapezoidalMethod trapezoidComp = new TrapezoidalMethod();
                methodComponents.Add(trapezoidComp);
                richTextBox1.Text += (trapezoidComp.Integration(formulaComp, a, b, eps).ToString()
                                      + " (метод трапеций)\n");
            }
            if (checkBox3.Checked)
            {
                SimpsonMethod simpsonComp = new SimpsonMethod();
                methodComponents.Add(simpsonComp);
                richTextBox1.Text += (simpsonComp.Integration(formulaComp, a, b, eps).ToString()
                                      + " (метод Симпсона)\n");
            }
            methodComponents.Dispose();
            formulaComp.Dispose();
        }
예제 #4
0
        public double Integration(FormulaExecutor integrand, double a, double b, double eps)
        {
            //заменим особые предельные точки на точки из окрестности
            if (Double.IsNaN(integrand.Execute(a)) || Double.IsInfinity(integrand.Execute(a)))
            {
                a += 0.0001 * eps * (b - a);
            }
            if (Double.IsNaN(integrand.Execute(b)) || Double.IsInfinity(integrand.Execute(b)))
            {
                b -= 0.0001 * eps * (b - a);
            }
            //посчитаем производную на 100 точках и определим шаг разбиения h для метода
            int n = 1000;

            double[] deriv = new double[n];
            deriv[0] = (integrand.Execute(a + (b - a) / (n - 1)) - integrand.Execute(a)) / ((b - a) / (n - 1));
            for (int i = 1; i < n; ++i)
            {
                deriv[i] = (integrand.Execute(a + i * (b - a) / (n - 1)) - integrand.Execute(a + (i - 1) * (b - a) / (n - 1))) / ((b - a) / (n - 1));
            }
            //по значению производной посчитаем значение второй производной  и определим шаг разбиения h для метода
            double[] secDeriv = new double[n];
            secDeriv[0] = (deriv[1] - deriv[0]) / ((b - a) / (n - 1));
            double maxSecDeriv = Math.Abs(secDeriv[0]);

            for (int i = 1; i < n; ++i)
            {
                secDeriv[i] = (deriv[i] - deriv[i - 1]) / ((b - a) / (n - 1));
                if (Math.Abs(secDeriv[i]) > maxSecDeriv)
                {
                    maxSecDeriv = Math.Abs(secDeriv[i]);
                }
            }
            double h = (b - a) / Math.Ceiling(Math.Sqrt(maxSecDeriv * Math.Pow(b - a, 3) / (12 * eps)));
            //найдем значение интеграла
            double sum = integrand.Execute(a) + integrand.Execute(b);

            for (int i = 1; i *h < (b - a); ++i)
            {
                sum += 2 * integrand.Execute(a + i * h);
            }
            return(0.5 * h * sum);
        }
예제 #5
0
        public double Integration(FormulaExecutor integrand, double a, double b, double eps)
        {
            //заменим особые предельные точки на точки из окрестности
            if (Double.IsNaN(integrand.Execute(a)) || Double.IsInfinity(integrand.Execute(a)))
            {
                a += 0.0001 * eps * (b - a);
            }
            if (Double.IsNaN(integrand.Execute(b)) || Double.IsInfinity(integrand.Execute(b)))
            {
                b -= 0.0001 * eps * (b - a);
            }
            //посчитаем производную на 100 точках и определим шаг разбиения h для метода
            int n = 100;

            double[] deriv = new double[n];
            deriv[0] = (integrand.Execute(a + (b - a) / (n - 1)) - integrand.Execute(a)) / ((b - a) / (n - 1));
            double maxDeriv = Math.Abs(deriv[0]);

            for (int i = 1; i < n; ++i)
            {
                deriv[i] = (integrand.Execute(a + i * (b - a) / (n - 1)) - integrand.Execute(a + (i - 1) * (b - a) / (n - 1))) / ((b - a) / (n - 1));
                if (Math.Abs(deriv[i]) > maxDeriv)
                {
                    maxDeriv = Math.Abs(deriv[i]);
                }
            }
            double h = (b - a) / Math.Ceiling(0.5 * maxDeriv * (b - a) * (b - a) / eps);
            //найдем значение интеграла
            double sum = 0;

            for (int i = 0; i *h < (b - a); ++i)
            {
                sum += integrand.Execute(a + i * h);
            }
            return(sum * h);
        }