2008-09-02 2 views
22

Как вычислить значение PI с использованием C#?Как рассчитать PI в C#?

Я думал, что это будет через рекурсивную функцию, если да, то как бы она выглядела и есть математические уравнения для ее поддержки?

Я не слишком суетлив к производительности, в основном, как это сделать с учебной точки зрения.

+0

[Этот вопрос] (http://stackoverflow.com/questions/19/fastest-way-to -get-value-of-pi) имеет множество хороших решений с алгоритмической точки зрения. Я бы не подумал, что будет сложно адаптировать один из них к C#. – 2008-09-02 12:40:57

ответ

40

Если вы хотите рекурсии:

PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...)))) 

Это стало бы, после некоторого переписывания:

PI = 2 * F(1); 

с F (I):

double F (int i) { 
    return 1 + i/(2.0 * i + 1) * F(i + 1); 
} 

Исаак Ньютон (возможно, слышал о нем раньше;)) придумал этот трюк. Обратите внимание, что я оставил конечное условие, чтобы оно было простым. В реальной жизни вы нуждаетесь в этом.

+0

Кроме того, вам нужно вернуть значение? – JFA 2013-10-17 03:39:53

+3

@jack У него нет условия завершения или возвращаемого значения. Если вы хотите создать полный рабочий пример, я предлагаю вам опубликовать новый ответ.См. Комментарий в ответе `Обратите внимание, что я не учитывал конечное условие, чтобы оно было простым. В реальной жизни вы нуждаетесь в этом. ` – dcaswell 2013-10-17 03:53:02

+4

как у этого так много upvotes? это не возвращает ** ничего ** – Guy 2014-03-07 12:57:59

1

Рассчитайте так:

x = 1 - 1/3 + 1/5 - 1/7 + 1/9 (... etc as far as possible.) 
PI = x * 4 

У вас есть Пи !!!

Это самый простой способ, о котором я знаю.

Значение PI медленно сходится к фактическому значению Pi (3.141592165 ......). Если вы повторяете больше раз, тем лучше.

20

Как об использовании:

double pi = Math.PI; 

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

+3

Я думаю, что это редкий случай, когда вам нужно иметь больше точности, чем вы получаете от Math.PI; – 2010-02-12 23:12:25

0

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

(если вы пишете научную специальное программное обеспечение 'Пи' ...)

4

Хороший обзор различных алгоритмов:

Я не уверен в сложности, заявленной для алгоритма Гаусса-Лежандра-Саламина в первом звене (я бы сказал, O (N log^2 (N) log (log (N)))) ,

Я рекомендую вам попробовать, однако, конвергенция действительно быстро.

Кроме того, я не совсем уверен, зачем пытаться преобразовать довольно простой процедурный алгоритм в рекурсивный?

Обратите внимание: если вы заинтересованы в производительности, то работа с ограниченной точностью (как правило, требующая «double», «float», ... output) на самом деле не имеет смысла, поскольку очевидный ответ в такой случай просто для того, чтобы жестко определить значение.

0

... Что касается

... как идти об этом с учебной точки зрения.

Вы пытаетесь научиться программировать научные методы? или для производства программного обеспечения для производства? Я надеюсь, что сообщество увидит это как правильный вопрос, а не нитпик.

В любом случае, я думаю, что написать свой собственный Pi - это проблема. Дмитрий уже показал константу «Math.PI». Атакуйте еще одну проблему в одном пространстве! Пойдите для общих аппроксимаций Ньютона или что-то пятно.

1

Вот хороший подход (от the main Wikipedia entry on pi); он сходится намного быстрее, чем простая формула, рассмотренная выше, и вполне поддается рекурсивному решению, если вы намерены продолжить рекурсию в качестве учебного упражнения. (Предполагая, что вы после опыта обучения, я не даю никакого реального кода.)

Основная формула такая же, как и выше, но этот подход усредняет частичные суммы для ускорения конвергенции.

Определим две функции параметра, круговую (Н, W), так что:

pie(0,1) = 4/1 
pie(0,2) = 4/1 - 4/3 
pie(0,3) = 4/1 - 4/3 + 4/5 
pie(0,4) = 4/1 - 4/3 + 4/5 - 4/7 
... and so on 

Так что ваша первая возможность изучить рекурсию, чтобы закодировать, что «горизонтальный» вычисление как «ширина» параметра увеличивается (для «высоты» нуля).

Затем добавить второе измерение с этой формулой:

pie(h, w) = (pie(h-1,w) + pie(h-1,w+1))/2 

, который используется, конечно, только для значений ч больше нуля.

Приятная вещь в этом алгоритме заключается в том, что вы можете легко объединить его с электронной таблицей, чтобы проверить свой код, когда вы исследуете результаты, полученные по более крупным параметрам. К тому времени, когда вы вычислите пирог (10,10), вы получите приблизительное значение для pi, которое достаточно для большинства инженерных целей.

2

Что такое PI? Окружность круга делится на его диаметр.

В компьютерной графике вы можете нарисовать/нарисовать окружность с центром на 0,0 от начальной точки x, y, следующую точку x ', y' можно найти, используя простую формулу: x '= x + y/h: y '= y - x'/h

h обычно имеет мощность 2, так что разделение можно легко выполнить с помощью сдвига (или вычитания из показателя экспонента на двойном). h также хочет быть радиусом r вашего круга. Легкой начальной точкой будет x = r, y = 0, а затем подсчитать c числом шагов до x < = 0 для построения квадрата круга. PI составляет 4 * c/r или PI составляет 4 * c/h

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

6

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

atan (1) == PI/4, поэтому старый каштан, когда заслуживающая доверия функция дуги-касания присутствует 4 * atan (1).

Очень симпатичная оценка с фиксированным соотношением, которая делает старую западную 22/7 похожей на грязь. - это 355/113, которая хороша для нескольких десятичных знаков (как минимум, три или четыре, я думаю). В некоторых случаях это даже достаточно хорошо для целочисленной арифметики: умножьте на 355, затем разделите на 113.

355/113 также легко зафиксировать память (для некоторых людей в любом случае): считать один, один, три, три, пять, пять и помните, что вы набираете цифры в знаменателе и числителе (если вы забудете, какой триплет идет сверху, мысль микросекунды обычно собирается выправить).

Обратите внимание, что 22/7 дает вам: 3.14285714, что неверно на тысячных.

355/113 дает вам 3.14159292, что не является ошибкой до десятимиллионных.

Acc. на /usr/include/math.h на моей коробке, M_PI - это # ​​define'd как: 3.14159265358979323846 , который, вероятно, добрался до самого места.

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

355/113 - старая китайская оценка, и я считаю, что она предваряет 22/7 на многие годы. Меня научил профессор физики, когда я был несовершеннолетним.

0

@Thomas Kammeyer:

Обратите внимание, что Атан (1.0) довольно часто зашиты, так 4 * Атан (1,0) не является действительно «алгоритм», если вы вызываете функцию библиотеки Атан (довольно немногие уже предположили, что действительно, заменив Atan (x) на ряд (или бесконечное произведение) для него, а затем оценивая его при x = 1.

Кроме того, очень мало случаев, когда вам понадобится pi больше точность, чем несколько десятков бит (которая может быть легко жестко запрограммирована!) Я работал над приложениями в математике, где для вычисления некоторых (довольно сложных) математических объектов (которые были полиномиальны с целыми коэффициентами), I должен был выполнять арифметику на реальных и сложных числах (включая вычисления pi) с точностью до нескольких миллионов бит ... но это не очень часто «в реальной жизни» :)

Вы можете посмотреть следующее пример code.

1
Enumerable.Range(0, 100000000).Aggregate(0d, (tot, next) => tot += Math.Pow(-1d, next)/(2*next + 1)*4) 
6

Если вы внимательно посмотрите в это действительно хороший гид:

Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4

Вы найдете на странице 70 этой милой реализации (с незначительными изменениями с моей стороны):

static decimal ParallelPartitionerPi(int steps) 
{ 
    decimal sum = 0.0; 
    decimal step = 1.0/(decimal)steps; 
    object obj = new object(); 

    Parallel.ForEach(
     Partitioner.Create(0, steps), 
     () => 0.0, 
     (range, state, partial) => 
     { 
      for (int i = range.Item1; i < range.Item2; i++) 
      { 
       decimal x = (i - 0.5) * step; 
       partial += 4.0/(1.0 + x * x); 
      } 

      return partial; 
     }, 
     partial => { lock (obj) sum += partial; }); 

    return step * sum; 
} 
0

Следующая ссылка показывает, как вычислить константу pi на основании ее определения как интеграла, который может быть записан как предел суммирования, это очень интересно ing: https://sites.google.com/site/rcorcs/posts/calculatingthepiconstant Файл «Pi как интеграл» объясняет этот метод, используемый в этом сообщении.

0

Мне нравится this paper, в котором объясняется, как рассчитать π на основе расширения серии Тейлора для Arctangent.

Бумага начинается с простым предположением, что

Атан (1) = π/4 радиана

Атан (х) может быть итеративно оценено с рядом Тейлора

atan (x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9 ...

В статье указывается, почему это не особенно эффективно и продолжает делать ряд логических уточнений в технике. Они также предоставляют примерную программу, которая вычисляет π до нескольких тысяч цифр, в комплекте с исходным кодом, включая требуемые математические процедуры с бесконечной точностью.

1
using System; 

namespace Strings 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

/*   decimal pie = 1; 
      decimal e = -1; 
*/ 
      var stopwatch = new System.Diagnostics.Stopwatch(); 
      stopwatch.Start(); //added this nice stopwatch start routine 

    //leibniz formula in C# - code written completely by Todd Mandell 2014 
/* 
      for (decimal f = (e += 2); f < 1000001; f++) 
      { 
       e += 2; 
       pie -= 1/e; 
       e += 2; 
       pie += 1/e; 
       Console.WriteLine(pie * 4); 
      } 

       decimal finalDisplayString = (pie * 4); 
       Console.WriteLine("pie = {0}", finalDisplayString); 
       Console.WriteLine("Accuracy resulting from approximately {0} steps", e/4); 
*/ 

// Nilakantha formula - code written completely by Todd Mandell 2014 
// π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) + 4/(10*11*12) - (4/(12*13*14) etc 

      decimal pie = 0; 
      decimal a = 2; 
      decimal b = 3; 
      decimal c = 4; 
      decimal e = 1; 

      for (decimal f = (e += 1); f < 100000; f++) 
      // Increase f where "f < 100000" to increase number of steps 
      { 

       pie += 4/(a * b * c); 

       a += 2; 
       b += 2; 
       c += 2; 

       pie -= 4/(a * b * c); 

       a += 2; 
       b += 2; 
       c += 2; 

       e += 1; 
      } 

      decimal finalDisplayString = (pie + 3); 
      Console.WriteLine("pie = {0}", finalDisplayString); 
      Console.WriteLine("Accuracy resulting from {0} steps", e); 

      stopwatch.Stop(); 
      TimeSpan ts = stopwatch.Elapsed; 
      Console.WriteLine("Calc Time {0}", ts); 

      Console.ReadLine(); 

     } 
    } 
} 
1
public static string PiNumberFinder(int digitNumber) 
    { 
     string piNumber = "3,"; 
     int dividedBy = 11080585; 
     int divisor = 78256779; 
     int result; 

     for (int i = 0; i < digitNumber; i++) 
     { 
      if (dividedBy < divisor) 
       dividedBy *= 10; 

      result = dividedBy/divisor; 

      string resultString = result.ToString(); 
      piNumber += resultString; 

      dividedBy = dividedBy - divisor * result; 
     } 

     return piNumber; 
    } 
0

Во-первых, обратите внимание, что C# можно использовать поле Math.PI рамок .NET:

https://msdn.microsoft.com/en-us/library/system.math.pi(v=vs.110).aspx

Приятной особенностью является то, что это полная точность вдвое больше, вы можете использовать или сравнить с вычисленными результатами. Вкладки этого URL имеют похожие константы для C++, F # и Visual Basic.

Чтобы вычислить больше мест, вы можете написать собственный код расширенной точности. Тот, который быстро кодировать и достаточно быстро и легко программы:

Pi = 4 * [4 * агс (1/5) - арктангенс (1/239)]

Эта формула и многие другие, в том числе некоторые, которые сходятся по удивительно быстрыми темпами, например, 50 цифр, в перспективе, находятся на Wolfram:

Wolfram Pi Formulas

Смежные вопросы