파이가 여전히 잘못되었습니다.


27

파이가 잘못되었습니다

pi를 계산하는 일반적인 방법은 "다트"를 1x1 상자에 던지고 던진 총계와 비교하여 유닛 서클의 어느 땅을 보는 것입니다.

loop
   x = rand()
   y = rand()
   if(sqrt(x*x + y*y) <= 1) n++
   t++
pi = 4.0*(n/t)

보이는 프로그램 작성pi를 올바르게 계산해야하는 (이 또는 다른 일반적인 pi 계산 방법을 사용하여) tau를 계산 (타우 = 2 * PI = 6.283185307179586 ...)를 대신. 코드는 최소한 처음 6 자리를 생성해야합니다. 6.283185

우승자는 6 월 6 일 (오늘부터 1 주일)에 선정되었습니다.


43
우승자가 6 월 28 일에 선정되지 않은 이유는 무엇입니까?
corsiKa

9
인기 콘테스트에서 우승자가 선정되어야하는 이유를 잘 모르겠습니다.
Tim S.

1
나는 그것을 얻지 못한다. 이것은 리턴하는 것처럼 1보이지만 리턴 하는 함수를 요청하는 것과 같습니다 2. 우리는 누구를 속이고 있습니까?
ja72

3
@ ja72 코드의 독자 :)
tomsmeding

8
누구나 pau가 옳다는 것을 알고 있습니다. : P
Justin Krejcha 2016 년

답변:


57

자바 스크립트

alert(Math.atan2(0, -0) - Math.atan2(-0, -0) + Math.atan2(0, 0))

도와주세요, 나는 우주 공장에 갇혀 있고 , 내가 무엇을하고 있는지 잘 모르겠습니다. Math.atan2좋은 값으로 파이를 반환해야합니까? Math.atan2(0, -0)pi를 반환하므로 빼고 더하면 pi가 있어야합니다.


14
난 그냥 누워서 울고 있다고 생각합니다. Goddamnit, JavaScript.
Jack M

3
설명 부탁 해요? :)
Jaa-c

2
x 축과 점 (Y, X) 사이의 시계 반대 방향 각도 (라디안). Y 지점의 부호는 이것이 양의 각도인지 음의 각도인지를 결정하며 다음과 같이됩니다π - (-π)

8
0_o>>> 0 === -0 ;true ;>>> Math.atan2(0, 0) ;0 ;>>> Math.atan2(0, -0) ;3.141592653589793
Izkata

5
@JackM, 그 진술은 항상 말하기에 적절합니다 :)이 경우 IEEE 표준에 기인하고 많은 언어 (JS뿐만 아니라)에 0 대 음수 0 문제가 있습니다.
Paul Draper

40

기본

(더 구체적으로, 다람쥐 기본 )

이것은 15 세기에 Nilakantha Somayaji가 발견 한 무한 시리즈를 사용합니다 .

' Calculate pi using the Nilakantha series:
'               4       4       4       4
'  pi  =  3 + ----- - ----- + ----- - ------ + ...
'             2x3x4   4x5x6   6x7x8   8x9x10
i = pi = 0
numerator = -4
while i<10000
  i = i + 2
  numerator = -numerator
  pi = pi + numerator / (i * (i+1) * (i+2))
wend
pi = pi + 3
print using "#.##########";pi

산출

6.2831853072

무슨 일이 일어나고 있는지 알 수 없다면 몇 가지 힌트가 있습니다.

Chipmunk Basic에서 변수 pi 는 프로그램 실행을 시작할 때 π 값으로 사전 설정됩니다.

BASIC에서 등호는 변수 할당과 등식 테스트에 모두 사용됩니다. 따라서 a = b = ca = (b == c) 로 해석됩니다 .


기다리지 않아요, 그래서 ifalse습니까? 그리고 당신 2은 그것에 추가 ? 그리고 작동합니까 ???
Dunno

2
@ Dunno : 물론, 루프가 시작 i == false되는 것과 비슷합니다 i == 0. 요점은 누산기의 초기 값 pi이 0이 아니라는 것입니다.
Bergi

1
@ Bergi 그래, 난 그냥 내 사실을 주위에 머리를 감싸 수 없습니다 false + 2 == 2: D
Dunno

@Dunno 동적 타이핑 등 : 산술을 수행 할 때 false가 암시 적으로 0으로 변환됩니다. 또한 C에서 bool유형 이 부족 하고 똑같이 00을 나타내며 회답 적 으로 표현 하는 똑같은 명백한 동작이 있습니다. 그것이 우아하지는 않지만, 그것이 작동하는 방식입니다. falsetrue
Suzanne Dupéron 2016 년

15

C-반원의 길이

π 를 계산하는 한 가지 방법 은 단순히 (1, 0)중심으로 회전 할 때 점이 이동 하는 거리를 측정하는 것입니다 . 이는 의 원주 ( ) 의 절반이되기 때문입니다 .(-1, 0)

여기에 이미지 설명을 입력하십시오

그러나, sin(x)또는 cos(x)이 있기 때문에 필요에 의해 수행 될 수 없다 스테핑 주위에 모든 방법을 기원 하고 요점은 각 단계에 대한 이동 거리를 추가 . 각 단계의 크기가 작을수록 더 정확한 π 를 얻을 수 있습니다.

참고 : 스테핑은 y가 0보다 작을 때 종료됩니다 (이것이 통과하는 것과 같습니다 (-1, 0)).

#include <stdio.h>                          // for printf
#define length(y, x) ((x * x) + (y * y))
int main()
{
    double x, y;
    double pi, tau, step;
    // start at (2, 0) which actually calculates tau
    x  = 2;
    y  = 0;
    // the step needs to be very low for high accuracy
    step = 0.00000001;  
    tau = 0;
    while (y >= 0)
    {   // the derivate of (x, y) is itself rotated 90 degrees
        double dx = -y;
        double dy = x;

        tau += length(dx, dy) * step; // add the distance for each step to tau
        // add the distance to the point (make a tiny rotation)
        x += dx * step;
        y += dy * step;
    }
    pi = tau / 2;   // divide tau with 2 to get pi

    /* ignore this line *\                      pi *= 2;    /* secret multiply ^-^ */

    // print the value of pi
    printf("Value of pi is %f", pi); getchar(); 
    return 0;
}

다음과 같은 출력을 제공합니다.

Value of pi is 6.283185

3
합법적 인 것 같습니다 ... 확실히.
bjb568

1
귀하의 length매크로는 SQRT 없습니다. 그게 의도입니까? x그리고 y정의와 호출 사이에 교환됩니다 (효과 없음)
Ben Voigt

@BenVoigt hhh! 트릭을 망치지 말고 그렇습니다. sqrt실수 PI의 값을 알아 차린에도 +1 ... 6,28로 인쇄가되도록 생략 x하고 y있는 난하지 않았다!
Thism2

1
오, 이제 나는 당신이 단위 원이 아니라 반경 2를 가진 것을 추적하고 있음을 알았습니다.
Ben Voigt

7
어떻게 작동하는지 이해하기 전에 그 라인을 무시하지 않고 몇 분을 낭비했다고 고백해야합니다.
loreb

10

기음

(이것은 의도 된 것보다 길어졌지만 어쨌든 게시 할 것입니다 ...)

17 세기에 Wallis는 Pi에 대한 무한 시리즈를 발표했습니다.

여기에 이미지 설명을 입력하십시오

( π, e 및 √ (2 + √2에 대한 새로운 월리스 및 카탈로니아 어 유형 무한 제품 참조 ) 참조)

이제 Pi를 계산하려면 먼저 분모를 빼기 위해 2를 곱해야합니다.

여기에 이미지 설명을 입력하십시오

내 솔루션은 Pi / 2 및 2에 대한 무한 계열을 계산 한 다음 두 값을 곱합니다. 최종 값을 계산할 때 무한 제품의 수렴 속도가 매우 느립니다.

산출:

pi: 6.283182
#include "stdio.h"
#include "stdint.h"

#define ITERATIONS 10000000
#define one 1

#define IEEE_MANTISSA_MASK 0xFFFFFFFFFFFFFULL

#define IEEE_EXPONENT_POSITION 52
#define IEEE_EXPONENT_BIAS 1023

// want to get an exact as possible result, so convert
// to integers and do custom 64-bit multiplication.
double multiply(double aa, double bb)
{
    // the input values will be between 1.0 and 2.0
    // so drop these to less than 1.0 so as not to deal 
    // with the double exponents.
    aa /= 2;
    bb /= 2;

    // extract fractional part of double, ignoring exponent and sign
    uint64_t a = *(uint64_t*)&aa & IEEE_MANTISSA_MASK;
    uint64_t b = *(uint64_t*)&bb & IEEE_MANTISSA_MASK;

    uint64_t result = 0x0ULL;

    // multiplying two 64-bit numbers is a little tricky, this is done in two parts,
    // taking the upper 32 bits of each number and multiplying them, then
    // then doing the same for the lower 32 bits.
    uint64_t a_lsb = (a & 0xFFFFFFFFUL);
    uint64_t b_lsb = (b & 0xFFFFFFFFUL);

    uint64_t a_msb = ((a >> 32) & 0xFFFFFFFFUL);
    uint64_t b_msb = ((b >> 32) & 0xFFFFFFFFUL);

    uint64_t lsb_result = 0;
    uint64_t msb_result = 0;

    // very helpful link explaining how to multiply two integers
    // http://stackoverflow.com/questions/4456442/interview-multiplication-of-2-integers-using-bitwise-operators
    while(b_lsb != 0)
    {
        if (b_lsb & 01)
        {
            lsb_result = lsb_result + a_lsb;
        }
        a_lsb <<= 1;
        b_lsb >>= 1;
    }
    while(b_msb != 0)
    {
        if (b_msb & 01)
        {
            msb_result = msb_result + a_msb;
        }
        a_msb <<= 1;
        b_msb >>= 1;
    }

    // find the bit position of the most significant bit in the higher 32-bit product (msb_answer)
    uint64_t x2 = msb_result;
    int bit_pos = 0;
    while (x2 >>= 1)
    {
        bit_pos++;
    }

    // stuff bits from the upper 32-bit product into the result, starting at bit 51 (MSB of mantissa)
    int result_position = IEEE_EXPONENT_POSITION - 1;
    for(;result_position > 0 && bit_pos > 0; result_position--, bit_pos--)
    {
        result |= ((msb_result >> bit_pos) & 0x01) << result_position;
    }

    // find the bit position of the most significant bit in the lower 32-bit product (lsb_answer)
    x2 = lsb_result;
    bit_pos = 0;
    while (x2 >>= 1)
    {
        bit_pos++;
    }

    // stuff bits from the lowre 32-bit product into the result, starting at whatever position
    // left off at from above.
    for(;result_position > 0 && bit_pos > 0; result_position--, bit_pos--)
    {
        result |= ((lsb_result >> bit_pos) & 0x01) << result_position;
    }

    // create hex representation of the answer
    uint64_t r = (uint64_t)(/* exponent */ (uint64_t)IEEE_EXPONENT_BIAS << IEEE_EXPONENT_POSITION) |
            (uint64_t)( /* fraction */ (uint64_t)result & IEEE_MANTISSA_MASK);

    // stuff hex into double
    double d = *(double*)&r;

    // since the two input values were divided by two,
    // need to multiply by four to fix the result.
    d *= 4;

   return d;
}

int main()
{
    double pi_over_two = one;
    double two = one;

    double num = one + one;
    double dem = one;

    int i=0;

    i=ITERATIONS;
    while(i--)
    {
        // pi = 2 2 4 4 6 6 8 8 ...
        // 2    1 3 3 5 5 7 7 9
        pi_over_two *= num / dem;

        dem += one + one;

        pi_over_two *= num / dem;

        num += one + one;
    }

    num = one + one;
    dem = one;

    i=ITERATIONS;
    while(i--)
    {
        // 2 = 2 4 4 6   10 12 12 14
        //     1 3 5 7    9 11 13 15
        two *= num / dem;

        dem += one + one;
        num += one + one;

        two *= num / dem;

        dem += one + one;

        two *= num / dem;

        dem += one + one;
        num += one + one;

        two *= num / dem;

        dem += one + one;
        num += one + one + one + one;
    }

    printf("pi: %f\n", multiply(pi_over_two, two));

    return 0;
}

이중 변환의 지수는 실제로 무시할 수 없습니다. 그것이 유일한 변화라면 (나눗셈을 2로 나누고, 4를 곱하고, 정수 곱셈을 남기십시오) 모든 것이 놀랍게 작동합니다.


8

자바-Nilakantha Series

Nilakantha 시리즈는 다음과 같이 제공됩니다.

pi = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) ...

따라서 각 항에 대해 분모는 연속 정수를 곱하여 시작하며 각 항은 2 씩 증가합니다. 대체 용어를 추가 / 빼기합니다.

public class NilakanthaPi {
    public static void main(String[] args) {
        double pi = 0;
        // five hundred terms
        for(int t=1;t<500;t++){
            // each i is 2*term
            int i=t*2;
            double part = 4.0 / ((i*i*t)+(3*i*t)+(2*t));
            // flip sign for alternating terms
            if(t%2==0)
                pi -= part;
            else
                pi += part;
            // add 3 for first term
            if(t<=2)
                pi += 3;
        }
        System.out.println(pi);
    }
}

500 개의 용어를 사용한 후, pi에 대한 합리적인 추정치를 얻습니다.

6.283185311179568

4

C ++ : 상가 마 그라마의마다 바

이 무한 시리즈는 이제 Madhava-Leibniz 로 알려져 있습니다 .

시리즈

제곱근 48로 시작하여 (-3) -k / (2k + 1) 의 합의 결과에 곱하십시오 . 매우 간단하고 구현하기 쉽습니다.

long double findPi(int iterations)
{
    long double value = 0.0;

    for (int i = 0; i < iterations; i++) {
        value += powl(-3.0, -i) / (2 * i + 1);
    }

    return sqrtl(48.0) * value;
}

int main(int argc, char* argv[])
{
    std::cout << "my pi: " << std::setprecision(16) << findPi(1000) << std::endl;

    return 0;
}

산출:

my pi: 6.283185307179588

3

파이썬-Nilakantha 시리즈의 대안

이것은 상당히 이해하기 쉬운 파이를 계산하는 또 다른 무한 시리즈입니다.

여기에 이미지 설명을 입력하십시오

이 공식의 경우 6을 취하고 2의 분자와 두 개의 연속 정수와 그 합의 곱인 분모를 갖는 분수의 덧셈과 뺄셈을 교대로 시작하십시오. 이후의 각 분수는 1 씩 증가하는 정수 세트를 시작합니다. 이것을 몇 번이라도 수행하면 결과는 거의 pi에 가깝습니다.

pi = 6
sign = 1
for t in range(1,500):
i = t+1
   part = 2.0 / (i*t*(i+t))
   pi = pi + sign * part
   sign = - sign # flip sign for alternating terms  
print(pi)

6.283185를 제공합니다.


-1
#include "Math.h"
#include <iostream>
int main(){
    std::cout<<PI;
    return 0;
}

Math.h :

#include <Math.h>
#undef PI
#define PI 6.28

출력 : 6.28

#include "Math.h"는 #include와 동일하지 않지만 주 파일을 보면 거의 아무도 생각하지 않습니다. 분명히,하지만 비슷한 문제가 내가 작업중 인 프로젝트에 나타 났으며 오랫동안 발견되지 않았습니다.


그럼에도 불구하고 영리한 솔루션.
BobTheAwesome
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.