
C#
Как оптимизировать вычисление числа П? C#
Слишком долго вычисляется даже 10 знак после запятой т. к. для этого приходится ставить 10000000000 циклов :D Как можно оптимизировать код? Или лучше использовать другую формулу?


// Вычисление количества знаков после запятой числа Пи
using System;
using System.Text;
namespace Answer {
class Program {
static void Main() {
var pi = Pi(1000);
Console.WriteLine($"{pi}");
Console.ReadKey();
}
public static string Pi(int n) {
++n;
var pi = new StringBuilder(n);
var len = n * 10 / 3;
var rem = new int[len];
for (var i = 0; i < len; ++i) rem[i] = 2;
var dig = 0;
for (var i = 0; i < n; ++i) {
var carry = 0;
var sum = 0;
for (var j = len - 1; j >= 0; --j) {
rem[j] *= 10;
sum = rem[j] + carry;
var part = sum / (j * 2 + 1);
rem[j] = sum % (j * 2 + 1);
carry = part * j;
}
rem[0] = sum % 10;
var q = sum / 10;
if (q == 9) ++dig;
else if (q == 10) {
q = 0;
for (int k = 1; k <= dig; ++k) {
int rep = int.Parse(pi.ToString().Substring(i - k, 1));
if (rep == 9) rep = 0;
else ++rep;
pi.Remove(i - k, 1);
pi.Insert(i - k, rep);
}
dig = 1;
} else dig = 1;
pi.Append(q);
}
if (pi.Length >= 2) pi.Insert(1, '.');
return pi.ToString();
}
}
}
using System;
using System.Text;
namespace Answer {
class Program {
static void Main() {
var pi = Pi(1000);
Console.WriteLine($"{pi}");
Console.ReadKey();
}
public static string Pi(int n) {
++n;
var pi = new StringBuilder(n);
var len = n * 10 / 3;
var rem = new int[len];
for (var i = 0; i < len; ++i) rem[i] = 2;
var dig = 0;
for (var i = 0; i < n; ++i) {
var carry = 0;
var sum = 0;
for (var j = len - 1; j >= 0; --j) {
rem[j] *= 10;
sum = rem[j] + carry;
var part = sum / (j * 2 + 1);
rem[j] = sum % (j * 2 + 1);
carry = part * j;
}
rem[0] = sum % 10;
var q = sum / 10;
if (q == 9) ++dig;
else if (q == 10) {
q = 0;
for (int k = 1; k <= dig; ++k) {
int rep = int.Parse(pi.ToString().Substring(i - k, 1));
if (rep == 9) rep = 0;
else ++rep;
pi.Remove(i - k, 1);
pi.Insert(i - k, rep);
}
dig = 1;
} else dig = 1;
pi.Append(q);
}
if (pi.Length >= 2) pi.Insert(1, '.');
return pi.ToString();
}
}
}
Конечно, есть намного более эффективные формулы
https://ru.wikipedia.org/wiki/Пи_(число)#Эра_компьютерных_вычислений
https://ru.wikipedia.org/wiki/Пи_(число)#Эра_компьютерных_вычислений
Куаныш Бакенов
А что так сложно? :d
Алексей Шошин
А чтобы было быстро :) Проще всего ходить пешком. А пострить самолет куда сложнее. Есть множество приемов ускорения вычислений не только пи, но и вообще почти всяких действий математики. И чем больше будет выигрыш, тем сложнее формулы.
Один из самых простых подходов - это ряд Лейбница с асимптотическим уточнением. Я ниже его писал как π/4 = 1-⅓+¹/5-...-(-1)ⁿ/(2n-1). Просто так сам по себе он действительно сходится очень медленно, однако если к сумме приплюсовать небольшую добавку (читай о которой, например, в соответствующей статейке Википедии !), число π с точностью, близкую к машинной для чисел типа double или decimal вычислится довольно быстро !
А вот ещё один метод (причём несколько даже удивительный !):
√π = S{x=-∞;+∞}exp(-x²)dx.
Итак, интегрируем функцию число е в степени минус икс в квадрате по всей вещественной оси (с последующим возводением получившегося результата в квадрат) самым простым способом: численным методом трапеций, а вместо бесконечностей возьмём какие-нибудь небольшие числа - например, -10 и 10.
Пишем код:
double f(double x) { double y=x*x,p=1,s=1,k=0; while (p>1e-19) { k++; p*=y/k; s+=p; } return 1/s; }
int main() { int i,n=40; double a=-10,b=10,h=(b-a)/n,π=0.5*(f(a)+f(b)); for (i=1; i < n; i++) π+=f(a+i*h); π*=h; π*=π; Console.WriteLine("π = "+π); }
Удивляет тут то, что десятка - это не бесконечность, шаг интегрирования h=0.5 - ну никак не бесконечно малая, а интегрирование по методу трапеций - вовсе никакое не точное, а результат получается почему-то удивительно точным !..
Можно воспользоваться также суммой обратных биквадратов, которая сходится быстро, в отличии от суммы обратных квадратов, которая сходится медленно и неточно:
S{n=1;∞}¹/n⁴ = π⁴/90
S{n=1;∞}¹/n² = π²/6
Для вычисления обоих этих сумм тоже есть ускоряющие асимптотические уточнения - советую их тебе вывести самому, чтобы можно было ограничится несколькими сотнями (или даже десятками !) слагаемыми, а не сотнями миллионов !..
А вот ещё один метод (причём несколько даже удивительный !):
√π = S{x=-∞;+∞}exp(-x²)dx.
Итак, интегрируем функцию число е в степени минус икс в квадрате по всей вещественной оси (с последующим возводением получившегося результата в квадрат) самым простым способом: численным методом трапеций, а вместо бесконечностей возьмём какие-нибудь небольшие числа - например, -10 и 10.
Пишем код:
double f(double x) { double y=x*x,p=1,s=1,k=0; while (p>1e-19) { k++; p*=y/k; s+=p; } return 1/s; }
int main() { int i,n=40; double a=-10,b=10,h=(b-a)/n,π=0.5*(f(a)+f(b)); for (i=1; i < n; i++) π+=f(a+i*h); π*=h; π*=π; Console.WriteLine("π = "+π); }
Удивляет тут то, что десятка - это не бесконечность, шаг интегрирования h=0.5 - ну никак не бесконечно малая, а интегрирование по методу трапеций - вовсе никакое не точное, а результат получается почему-то удивительно точным !..
Можно воспользоваться также суммой обратных биквадратов, которая сходится быстро, в отличии от суммы обратных квадратов, которая сходится медленно и неточно:
S{n=1;∞}¹/n⁴ = π⁴/90
S{n=1;∞}¹/n² = π²/6
Для вычисления обоих этих сумм тоже есть ускоряющие асимптотические уточнения - советую их тебе вывести самому, чтобы можно было ограничится несколькими сотнями (или даже десятками !) слагаемыми, а не сотнями миллионов !..
Похожие вопросы
- Как сгенерировать случайные числа в C#?
- C#. Как сгенерировать случайное число в диапозоне, исключающее одно число. C#
- Написать программу на C# вычисления стоимости покупки с учетом скидки.
- C#: Умножения чисел(чисел в строках) больших Int64 MaxValue без использования System.Numerics и BigInteger
- Программирование на C# - целые числа
- Составление алгоритма и программы вычисления
- [c#] как найти все простые делители числа, ответ в массиве int
- Стоит ли дальше учить C#?
- Программирование на C Sharp (C#)
- Сегодня начал учить c#, решил сделать калькулятор простой и столкнулся с такой ошибкой при компиляции, хелпуйте.