문제

C#을 사용하여 PI 값을 어떻게 계산할 수 있나요?

나는 그것이 재귀 함수를 통해서일 것이라고 생각했습니다. 그렇다면 그것은 어떻게 생겼을 것이며 그것을 뒷받침할 수학 방정식이 있습니까?

나는 성능에 대해 그다지 까다롭지 않습니다. 주로 학습 관점에서 수행하는 방법입니다.

도움이 되었습니까?

해결책

재귀를 원할 경우:

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);
}

아이작 뉴턴(당신은 이전에 그에 대해 들어본 적이 있을 것입니다;)) 이 트릭을 생각해냈습니다.단순하게 유지하기 위해 최종 조건을 생략했습니다.실생활에서는 일종의 것이 필요합니다.

다른 팁

다음을 사용하는 것은 어떻습니까?

double pi = Math.PI;

그보다 더 나은 정밀도를 원한다면 알고리즘 시스템과 Decimal 유형을 사용해야 합니다.

이 정말 좋은 가이드를 자세히 살펴보면 다음과 같습니다.

병렬 프로그래밍 패턴:.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;
}

여기에는 볼 수 없다는 사실에 정말 놀랐던 몇 가지 정말 오래된 트릭이 있습니다.

atan (1) == PI/4, 신뢰할 수있는 아크 텐트 기능이있을 때 오래된 밤은 4*atan (1)입니다.

오래된 서양 22/7을 먼지처럼 보이게하는 매우 귀엽고 고정 된 비율 추정치는 355/113이며, 이는 소수점 이하 자리 (최소 3-4 개)에 좋습니다.어떤 경우에는 정수 연산에 충분할 수도 있습니다.355를 곱한 다음 113으로 나눕니다.

355/113은 또한 기억하기 쉽습니다(어떤 사람들에게는 어쨌든):하나, 하나, 셋, 셋, 다섯, 다섯을 세고 분모와 분자에 있는 숫자의 이름을 지정한다는 것을 기억하세요(어떤 세 쌍이 맨 위에 있는지 잊어버린 경우 마이크로초 정도의 생각만으로 문제를 바로잡을 수 있습니다).

22/7은 다음을 제공합니다.3.14285714, 이는 천분의 일 단위로 잘못된 것입니다.

355/113은 3.14159292를 제공하며 이는 천만분의 1까지 틀린 것이 아닙니다.

Acc.내 상자의 /usr/include/math.h에 M_PI는 다음과 같이 #정의됩니다.3.14159265358979323846 아마도 아마도 좋을 것입니다.

PI를 추정하면 얻을 수있는 교훈은 많은 방법이 있으며, 완벽한 방법은 없으며, 의도 된 용도로 정렬해야한다는 것입니다.

355/113은 중국의 오래된 추정치이며 22/7보다 수년 앞선 것으로 생각됩니다.제가 학부 때 물리학 교수님께서 가르쳐주신 내용입니다.

다양한 알고리즘에 대한 좋은 개요:

첫 번째 링크에서 Gauss-Legendre-Salamin 알고리즘에 대해 주장된 복잡성에 대해 잘 모르겠습니다(O(N log^2(N) log(log(N)))).

시도해 보시기를 권장합니다. 하지만 수렴은 정말 빠른.

그리고 왜 아주 간단한 절차적 알고리즘을 재귀적인 알고리즘으로 변환하려고 하는지 잘 모르겠습니다.

성능에 관심이 있다면 제한된 정밀도로 작업하십시오(일반적으로 'double', 'float' 등이 필요함).출력)은 실제로 의미가 없습니다. 이 경우 확실한 대답은 단지 값을 하드코딩하는 것이기 때문입니다.

다음은 C#에서 PI 계산에 대한 기사입니다.

http://www.boyet.com/Articles/PiCalculator.html

PI란 무엇입니까?원의 둘레를 지름으로 나눈 값입니다.

컴퓨터 그래픽에서는 초기 점 x,y에서 중심이 0,0인 원을 플롯/그릴 수 있으며 다음 점 x',y'는 간단한 공식을 사용하여 찾을 수 있습니다.x' = x + y / h:y' = y - x' / h

h는 일반적으로 2의 거듭제곱이므로 쉬프트(또는 double의 지수에서 빼기)로 쉽게 나눌 수 있습니다.h는 또한 원의 반경 r이 되기를 원합니다.쉬운 시작점은 x = r, y = 0이고 x <= 0이 될 때까지 c 단계 수를 계산하여 원의 4분의 1을 그리는 것입니다.PI는 4 * c / r 또는 PI는 4 * c / h입니다.

매우 깊은 재귀는 일반적으로 상용 프로그램에서는 실용적이지 않지만 꼬리 재귀를 사용하면 루프로 구현되는 동안 알고리즘을 재귀적으로 표현할 수 있습니다.재귀 검색 알고리즘은 때때로 프로세스의 스택이 아닌 대기열을 사용하여 구현될 수 있으며, 검색은 막다른 곳에서 역추적하여 다른 경로를 취해야 합니다. 이러한 역추적 지점은 대기열에 들어갈 수 있으며 여러 프로세스는 지점을 대기열에서 해제하고 다음을 시도할 수 있습니다. 다른 경로.

다음과 같이 계산하세요.

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

당신은 Pi를 얻었습니다 !!!

이것이 내가 아는 가장 간단한 방법이다.

PI 값은 천천히 실제 Pi 값(3.141592165......)으로 수렴됩니다.여러 번 반복할수록 좋습니다.

다음은 좋은 접근 방식입니다. pi의 주요 Wikipedia 항목);이는 위에서 논의한 간단한 공식보다 훨씬 빠르게 수렴하며, 학습 연습으로 재귀를 추구하려는 의도라면 재귀 솔루션에 상당히 적합합니다.(학습 경험을 추구한다고 가정하고 실제 코드를 제공하지 않습니다.)

기본 공식은 위와 동일하지만 이 접근 방식은 부분합의 평균을 계산하여 수렴을 가속화합니다.

다음과 같이 두 개의 매개변수 함수인 파이(h, 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

따라서 재귀를 탐색할 수 있는 첫 번째 기회는 "너비" 매개변수가 증가함에 따라("높이"가 0인 경우) "수평" 계산을 코딩하는 것입니다.

그런 다음 다음 수식을 사용하여 두 번째 차원을 추가합니다.

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

물론 이는 0보다 큰 h 값에만 사용됩니다.

이 알고리즘의 좋은 점은 점진적으로 더 큰 매개변수에 의해 생성된 결과를 탐색하면서 스프레드시트로 쉽게 모형화하여 코드를 확인할 수 있다는 것입니다.파이(10,10)을 계산할 때쯤이면 대부분의 엔지니어링 목적에 적합한 대략적인 파이 값을 얻게 됩니다.

Enumerable.Range(0, 100000000).Aggregate(0d, (tot, next) => tot += Math.Pow(-1d, next)/(2*next + 1)*4)
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();

         }
     }
 }
    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;
    }

어떤 프로덕션 시나리오에서든 원하는 소수점 이하 자릿수까지 값을 찾아 클래스가 접근할 수 있는 곳에 'const'로 저장하도록 강요합니다.

(과학적인 'Pi' 특정 소프트웨어를 작성하지 않는 한...)

에 관하여...

...학습의 관점에서 어떻게 해야 할까요?

과학적 방법을 프로그래밍하는 방법을 배우려고 하시나요?아니면 생산 소프트웨어를 생산하기 위해?커뮤니티가 이 질문을 멍청한 질문이 아닌 유효한 질문으로 여기기를 바랍니다.

어느 경우든 자신만의 Pi를 작성하는 것은 해결된 문제라고 생각합니다.Dmitry는 이미 'Math.PI' 상수를 보여주었습니다.같은 공간에서 또 다른 문제를 공격해보세요!일반적인 뉴턴 근사법이나 매끄러운 것을 찾으십시오.

@토마스 카메이어:

Atan(1.0)은 하드코딩되는 경우가 많기 때문에 라이브러리 Atan 함수를 호출하는 경우 4*Atan(1.0)은 실제로 '알고리즘'이 아닙니다. 시리즈(또는 무한 제품)를 만든 다음 x=1에서 평가합니다.

또한, 수십 비트보다 더 정밀한 파이가 필요한 경우는 거의 없습니다. (쉽게 하드코딩할 수 있습니다!)나는 (매우 복잡한) 수학적 객체(정수 계수를 갖는 다항식)를 계산하기 위해 최대 정밀도로 실수 및 복소수(pi 계산 포함)에 대한 산술을 수행해야 하는 수학 응용 프로그램 작업을 했습니다. 몇백만 비트...하지만 이는 '실생활'에서는 그리 자주 발생하지 않습니다. :)

다음 예를 찾아볼 수 있습니다. 암호.

좋아요 이 종이, Arctangent에 대한 Taylor 시리즈 확장을 기반으로 π를 계산하는 방법을 설명합니다.

이 논문은 다음과 같은 간단한 가정으로 시작합니다.

Atan(1) = π/4 라디안

Atan(x)는 Taylor 시리즈를 사용하여 반복적으로 추정할 수 있습니다.

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

이 논문에서는 이것이 특별히 효율적이지 않은 이유를 지적하고 계속해서 기술을 여러 가지 논리적으로 개선합니다.또한 필요한 무한 정밀도 수학 루틴을 포함하여 소스 코드가 포함된 π를 수천 자리까지 계산하는 샘플 프로그램도 제공합니다.

다음 링크는 합산의 극한으로 쓸 수 있는 적분 정의를 기반으로 파이 상수를 계산하는 방법을 보여줍니다. 매우 흥미롭습니다.https://sites.google.com/site/rcorcs/posts/calculatedthepicconstant"Pi as an 일체형" 파일은 이 게시물에 사용된 이 방법을 설명합니다.

먼저 C#에서는 .NET 프레임워크의 Math.PI 필드를 사용할 수 있습니다.

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

여기서 좋은 특징은 이것이 계산된 결과와 사용하거나 비교할 수 있는 완전 정밀도 double이라는 것입니다.해당 URL의 탭에는 C++, F# 및 Visual Basic에 대한 유사한 상수가 있습니다.

더 많은 자릿수를 계산하려면 확장 정밀도 코드를 직접 작성할 수 있습니다.코딩이 빠르고 합리적으로 빠르고 프로그래밍하기 쉬운 방법은 다음과 같습니다.

Pi = 4 * [4 * 아크탄(1/5) - 아크탄(1/239)]

이 공식과 용어당 50자리와 같이 놀랍도록 빠른 속도로 수렴하는 일부 공식을 포함한 많은 다른 공식이 Wolfram에 있습니다.

Wolfram Pi 공식

파이(π) 다음을 사용하여 계산할 수 있습니다. 무한 시리즈.다음은 두 가지 예입니다.

그레고리-라이프니츠 시리즈:

π/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ...

C# 방법:

public static decimal GregoryLeibnizGetPI(int n)
{
    decimal sum = 0;
    decimal temp = 0;
    for (int i = 0; i < n; i++)
    {
        temp = 4m / (1 + 2 * i);
        sum += i % 2 == 0 ? temp : -temp;
    }
    return sum;
}

닐라칸타 시리즈:

π = 3 + 4 / (2x3x4) - 4 / (4x5x6) + 4 / (6x7x8) - 4 / (8x9x10) + ...

C# 방법:

public static decimal NilakanthaGetPI(int n)
{
    decimal sum = 0;
    decimal temp = 0;
    decimal a = 2, b = 3, c = 4;
    for (int i = 0; i < n; i++)
    {
        temp = 4 / (a * b * c);
        sum += i % 2 == 0 ? temp : -temp;
        a += 2; b += 2; c += 2;
    }
    return 3 + sum;
}

입력 매개변수 n 두 함수 모두 반복 횟수를 나타냅니다.

Nilakantha 시리즈는 Gregory-Leibniz 시리즈와 비교하여 더 빠르게 수렴됩니다.다음 코드를 사용하여 메서드를 테스트할 수 있습니다.

static void Main(string[] args)
{
    const decimal pi = 3.1415926535897932384626433832m;
    Console.WriteLine($"PI = {pi}");

    //Nilakantha Series
    int iterationsN = 100;
    decimal nilakanthaPI = NilakanthaGetPI(iterationsN);
    decimal CalcErrorNilakantha = pi - nilakanthaPI;
    Console.WriteLine($"\nNilakantha Series -> PI = {nilakanthaPI}");
    Console.WriteLine($"Calculation error = {CalcErrorNilakantha}");
    int numDecNilakantha = pi.ToString().Zip(nilakanthaPI.ToString(), (x, y) => x == y).TakeWhile(x => x).Count() - 2;
    Console.WriteLine($"Number of correct decimals = {numDecNilakantha}");
    Console.WriteLine($"Number of iterations = {iterationsN}");

    //Gregory-Leibniz Series
    int iterationsGL = 1000000;
    decimal GregoryLeibnizPI = GregoryLeibnizGetPI(iterationsGL);
    decimal CalcErrorGregoryLeibniz = pi - GregoryLeibnizPI;
    Console.WriteLine($"\nGregory-Leibniz Series -> PI = {GregoryLeibnizPI}");
    Console.WriteLine($"Calculation error = {CalcErrorGregoryLeibniz}");
    int numDecGregoryLeibniz = pi.ToString().Zip(GregoryLeibnizPI.ToString(), (x, y) => x == y).TakeWhile(x => x).Count() - 2;
    Console.WriteLine($"Number of correct decimals = {numDecGregoryLeibniz}");
    Console.WriteLine($"Number of iterations = {iterationsGL}");

    Console.ReadKey();
}

다음 출력은 Nilakantha 시리즈가 100번의 반복으로 PI의 올바른 소수점 6자리를 반환하는 반면 Gregory-Leibniz 시리즈는 100만 번의 반복으로 PI의 올바른 소수점 5자리를 반환한다는 것을 보여줍니다.

enter image description here

내 코드를 테스트할 수 있습니다 >> 여기

좋은 방법은 다음과 같습니다.x에 대해 1부터 원하는 것까지 일련의 1/x^2를 계산합니다. 숫자가 클수록 파이 결과가 더 좋습니다.결과에 6을 곱하고 sqrt()에 적용합니다.다음은 C#의 코드입니다(기본만 해당).

static void Main(string[] args)
    {
        double counter = 0;
        for (double i = 1; i < 1000000; i++)
        {

            counter = counter + (1 / (Math.Pow(i, 2)));

        }
        counter = counter * 6;
        counter = Math.Sqrt(counter);
        Console.WriteLine(counter);
    }
public double PI = 22.0 / 7.0;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top