Представление факториалов как знаменателей в C # - PullRequest
0 голосов
/ 26 января 2019

Я пытаюсь создать программу, которая демонстрирует способ, которым вы можете приблизить число Эйлера. Формула, на которой я основываюсь, это 1 + 1/1! + 1/2! + 1/3! + 1/4! ... Всякий раз, когда я запускаю программу, она начинает правильно ее аппроксимировать, но после еще нескольких итераций аппроксимация начинает становиться бесконечно малой.

Программа ниже - моя попытка преобразовать формулу в код. Я предлагаю пользователю ввести количество итераций 1 / n! они хотели бы аппроксимировать e с (valItr), и число итераций представляется итерациями. Любая помощь очень ценится.

int iterations = 1;

        while (iterations <= valItr)

        {
            Double approxE = 1;
            approxE = approxE + (1 / denomPrev * multiPlier);
            denomPrev = denomPrev * multiPlier;

            iterations++;
            multiPlier++;

            Console.WriteLine(approxE);

        }

Ответы [ 4 ]

0 голосов
/ 26 января 2019

Альтернативный подход к тому же вычислению приводит к (очень) визуально более точному ответу.По аналогии с правилом Хорнера мы замечаем, например,

1+1/1!+1/2!+1/3! = 1 + (1/1)*(1 + (1/2)*(1+1/3))

, поэтому в C мы могли бы написать

double e = 1.0 + 1.0/N
    while ( --N >= 2)
    {   e = 1.0 + e/N;
    }
    return 1.0 + e;
0 голосов
/ 26 января 2019

Ваш код лучше, чем у Фарука, потому что ему нужно только O (n) умножений, в то время как ему нужно O (n ^ 2) умножений.Но у вас есть две ошибки в коде.Во-первых, вы назначаете approxE = 1 в каждом цикле.А во-вторых,

(1 / denomPrev * multiPlier)

оценивается как

(1 / denomPrev) * multiPlier

, это не то, что вы хотите.Если вы исправите ошибки, это будет работать.Но вы можете привести в порядок немного больше и получить что-то вроде этого:

int valItr = 20;
double denomPrev = 1;
double approxE = 1;

for (int iterations = 1; iterations <= valItr; ++iterations)
{
    denomPrev *= iterations;
    approxE += 1 / denomPrev;

    Console.WriteLine(iterations + ": " + approxE);
}

Результат совершенно правильный:

1: 2
2: 2,5
3: 2,66666666666667
4: 2,70833333333333
5: 2,71666666666667
6: 2,71805555555556
7: 2,71825396825397
8: 2,71827876984127
9: 2,71828152557319
10: 2,71828180114638
11: 2,71828182619849
12: 2,71828182828617
13: 2,71828182844676
14: 2,71828182845823
15: 2,71828182845899
16: 2,71828182845904
17: 2,71828182845905
18: 2,71828182845905
19: 2,71828182845905
20: 2,71828182845905
0 голосов
/ 26 января 2019

Проблема заключалась в том, что мне нужно было вычислить текущий знаменатель из предыдущего знаменателя ПРЕЖДЕ ЧЕМ я пытался вычислить 1 / n!

denomPrev = denomPrev * multiplier;              
approxE = approxE + (1 / denomPrev);

^ Это исправило.

0 голосов
/ 26 января 2019

Для того, что я вижу, двойные не очень точны для действительно маленьких рациональных чисел. Если вы используете десятичную дробь, вы можете идти точно, но вы получите ошибку с большим количеством дробей.

Итак, осталось воспользоваться внешней помощью.

С BigRational (BigInteger) вы можете работать с дробями в том виде, в каком они есть, и после этого делать математику.

class Program
{
    static void Main(string[] args)
    {
        int nInterations = 10;

        BigRational val = 1;

        for (int i = 1; i <= nInterations; i++)
        {
            val += 1 / Factorial(i);
            Console.WriteLine(i + ": " + val);
        }


        Console.Read();
    }

    public static BigRational Factorial(int n)
    {
        if (n == 1)
            return 1;
        else
            return n * Factorial(n - 1);
    }
}
//decimal
//1: 2
//2: 2,5
//3: 2,6666666666666666666666666667
//4: 2,7083333333333333333333333334
//5: 2,7166666666666666666666666667
//6: 2,7180555555555555555555555556
//7: 2,7182539682539682539682539683
//8: 2,7182787698412698412698412699
//9: 2,7182815255731922398589065256
//10: 2,7182818011463844797178130512
//double
//1: 2
//2: 2,5
//3: 2,66666666666667
//4: 2,70833333333333
//5: 2,71666666666667
//6: 2,71805555555556
//7: 2,71825396825397
//8: 2,71827876984127
//9: 2,71828152557319
//10: 2,71828180114638
//BigRational
//1: 2/1
//2: 5/2
//3: 8/3
//4: 65/24
//5: 163/60
//6: 1957/720
//7: 685/252
//8: 109601/40320
//9: 98641/36288
//10: 9864101/3628800

NuGet: установочный пакет BigRationalLibrary

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...