2 차 수렴으로 π 계산


20

양수를 취하고 2 차 수렴을 갖는 π를 계산하기 위해 반복 알고리즘의 단계를 n수행 하는 함수 또는 완전한 프로그램을 작성 n하십시오 (즉, 매 반복마다 정확한 자릿수의 약 두 배) 그런 다음 2 n 개의 올바른 자릿수를 포함하여 반환하거나 인쇄합니다 시작 3). 그러한 알고리즘 중 하나는 Gauss–Legendre 알고리즘 이지만 원하는 경우 다른 알고리즘을 자유롭게 사용할 수 있습니다.

예 :

입력 1→ 출력 3.1
입력 2→ 출력 3.141
입력 5→ 출력3.1415926535897932384626433832795

요구 사항 :

  • 알고리즘의 각 반복은 더하기, 빼기, 곱하기, 나누기, 거듭 제곱 및 근수 (정수 지수 /도)와 같은 일정한 수의 기본 연산을 수행해야합니다. "큰"정수 / 소수에 대한 각 연산은 1로 계산됩니다. 내부에 하나 이상의 루프가 관련된 경우 분명히, 삼각 함수와 복소수를 포함하는 힘은 기본 연산이 아닙니다.
  • 이 알고리즘에는 일정한 수의 연산이 있어야하는 초기화 단계가 있어야합니다.
  • 알고리즘이 2 n 개의 정확한 자릿수 를 얻기 위해 1 ~ 2 회 이상의 반복이 필요한 경우, n+2대신 최대 반복을 수행 할 수 있습니다 n.
  • 분명히 충분이 아니었다면, 올바른이 개 후 N 숫자, 프로그램이 있어야 하지 (예 : 더 정확한 숫자, 잘못된 숫자 또는 셰익스피어의 전집과 같은) 다른 작업을 인쇄 할 수 있습니다.
  • 프로그램은 n1에서 20까지의 값을 지원해야합니다 .
  • n현대 컴퓨터에서 프로그램은 = 20에 1 시간 이상 걸리지 않아야합니다 .
  • 프로그램은 알고리즘의 초기화 및 첫 번째 반복 후에 20 자리 이상의 정확한 숫자를 얻지 않아야합니다.
  • 프로그램은 무료 소프트웨어를 사용하여 Linux에서 실행 가능해야합니다.
  • 소스 코드는 ASCII 문자 만 사용해야합니다.

채점 :

간단한 코드 골프, 가장 짧은 코드가 승리합니다.

우승자:

승자는 Digital Trauma입니다. 마침내 n = 20에서 농담을했습니다. 그의 매우 빠른 파이썬 솔루션과 다른 알고리즘으로 인해 Primo에게 특별상이 수여됩니다. :)


1
이차 수렴은 error ~ N ^ (1/2) 입니다. 당신이 설명하는 것은 지수 수렴 오류 ~ 2 ^ (-N) 입니다.
yo '

@yo '당신은 위키 백과 가 잘못되었다고 말하고 있습니까?
aditsu

1
오해의 소지가 있습니다. "이차적 수렴"은 ~q^(n^2)거기의 첫 번째 부분과 ~q^2두 번째 부분에 있습니다.
yo '

1
나는 codegolf를 이해하지 못합니다 : 분명히 누구든지 이와 같은 단일 작업을 위해 자신의 프로그래밍 언어를 작성한 다음 0 바이트의 프로그램을 작성할 수 있습니까?
theonlygusti

2
@theonlygusti이는 것 표준 허점 과 실격 것
aditsu

답변:


14

dc, 99 바이트

골프 :

2?dsi1+^k1dddsa2v/sb4/stsp[lalb*vlalb+2/dla-d*lp*ltr-stsasblp2*spli1-dsi0<m]dsmxK2/1-klalb+d*4lt*/p

공백과 "가독성"에 대한 주석 :

2?dsi               # Push 2. push input n, duplicate and store in i
1+^k                # Set calculation precision to 2^(n+1)
1dddsa              # Push four 1s. Store 1st in a
2v/sb               # Store 1/sqrt(2) in b
4/st                # Store 1/4 in t
sp                  # Store 1 in p
[                   # Start iteration loop macro
lalb*v              # Save sqrt(a*b) on stack
lalb+2/d            # Save a[i+1] = (a[i]+b[i])/2 on stack and duplicate
la-d*lp*ltr-        # Save t-p(a[i]-a[i+1])^2 on the stack
st                  # Store t result from stack
sa                  # Store a result from stack
sb                  # Store b result from stack
lp2*sp              # Store 2p in p
li1-dsi0<m]         # Decrement iteration counter i; recurse into macro if < 0
dsmx                # Duplicate, store and run macro
K2/1-k              # Set display precision to 2^n-1
lalb+d*4lt*/        # Save (a+b)^2/4t on stack
p                   # Print result

dc몇 자리의 정밀도를 사용해야하는지 알아야합니다. 계산 정밀도는 최종 디스플레이 정밀도보다 높아야하므로 계산 정밀도는 2^(n+1)숫자 로 설정됩니다 . http://www.angio.net/pi/digits/pi1000000.txt 에 대해 n = 10으로 출력의 정확성을 확인했습니다 .

이것은 더 큰 n에 대해 극적으로 느려집니다. n = 12는 내 VM에서 1.5 분이 걸립니다. 몇 가지 다른 샘플을 실행하면 시간 복잡도가 O (e ^ n)입니다 (놀랍지 않음). 이것을 n = 20으로 추정하면 런타임은 233 일입니다. 오 잘 우주의 열사보다 적어도 낫습니다.

이것은 적당히 골프화됩니다-스택은 각 반복 계산 중에 임시 변수를 제거하는 데 사용되지만 스택을 더 많이 사용하여 스택을 더 많이 사용할 수 있습니다.

$ dc glpi.dc <<< 1
3.1
$ dc glpi.dc <<< 2
3.141
$ dc glpi.dc <<< 5
3.1415926535897932384626433832795
$ time dc glpi.dc <<< 7
3.1415926535897932384626433832795028841971693993751058209749445923078\
164062862089986280348253421170679821480865132823066470938446

real    0m0.048s
user    0m0.039s
sys 0m0.000s
$ 

당신이 마음에 들지 않으면 dc70 개 문자에 배치 출력, 당신은 환경 변수를 설정할 수 있습니다 DC_LINE_LENGTH0을 :

$ DC_LINE_LENGTH=0 dc glpi.dc <<< 8
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648
$ 

2
하하 "가독성" 실제로 dc에는 적용되지 않습니다. ;)
Alex A.

입력 5에 대해 32 자리 이상을 인쇄하는 것 같습니다
aditsu

나는 그것에 대한 규칙과 달리는 시간에 관한 규칙을 추가했습니다 (그러나 엄격하지는 않습니다). 또한 출력이 백 슬래시를 사용하여 여러 줄로 분할되는 방식이 마음에 들지 않습니다. DC의 한계입니까?
aditsu

나는 출력이 n = 6에 대해 잘못되었다는 것을 두려워한다
aditsu

1
훌륭합니다. 100 미만으로도 얻을 수 있습니다.) 공백 / 설명없이 실제 골프 99 문자 프로그램을 게시 할 수 있습니까?
aditsu

10

R, 156 바이트

Gauss-Legendre 알고리즘을 절대적으로 구현하여 파티를 시작합시다.

for(i in 1:scan()){if(i<2){a=p=Rmpfr::mpfr(1,2e6);t=a/4;b=t^t}else{x=(a+b)/2;b=(a*b)^.5;t=t-p*(a-x)^2;a=x;p=2*p};o=(a+b)^2/(4*t)};cat(Rmpfr::format(o,2^i))

언 골프 + 설명 :

# Generate n approximations of pi, where n is read from stdin
for (i in 1:scan()) {

    # Initial values on the first iteration
    if (i < 2) {
        a <- p <- Rmpfr::mpfr(1, 1e7)
        t <- a/4
        b <- t^t
    } else {
        # Compute new values
        x <- (a + b) / 2
        b <- (a*b)^0.5
        t <- t - p*(a - x)^2

        # Store values for next iteration
        a <- x
        p <- 2*p
    }

    # Approximate pi 
    o <- (a + b)^2 / (4*t)
}

# Print the result with 2^n digits
cat(Rmpfr::format(o, 2^i))

mpfr()기능은 Rmpfr패키지의 일부입니다 . mpfr첫 번째 인수를 값으로 사용하고 두 번째 인수를 정밀도 비트 수로 사용하여 객체를 만듭니다 . 우리는 지정 ap1, 그리고 정의하여 t기반으로 a(그리고 b기반으로 t의) mpfr네 개의 변수를 입력 propogates이되어 전역 정밀도를 유지.

앞에서 언급했듯이 Rmpfr"R 다중 정밀도 부동 소수점 신뢰성"의 약자 인 R 패키지가 필요합니다 . 패키지는 백그라운드에서 GMP를 사용합니다. 불행히도 base R은 고정밀 산술을 수행 할 수 없으므로 패키지 종속성이 있습니다.

없어 Rmpfr? 땀 없습니다. install.packages("Rmpfr")그리고 당신의 모든 꿈이 이루어질 것입니다.

공지 사항 2e6정밀도로 지정되었습니다. 즉, 우리는 2,000,000 비트의 정밀도를 가지며, 최소 n= 20의 정밀도를 유지하기에 충분 n합니다.

여기서의 접근 방식은 문자 그대로 Wikipedia 페이지의 수식을 역류하는 것입니다.하지만 어딘가에서 시작해야합니다.

모든 입력은 언제나 환영합니다!


나는 이것을 많이 다시 써야했지만 Peter Taylor 가 내 첫 점수에서 70 바이트를 떨어 뜨리는 데 도움이되었다는 것을 여전히 인정해야한다 . DigitalTrauma의 말로, "붐".


7

파이썬 2, 214 바이트

이 과제는 Decimal 모듈을 배우는 데 좋은 변명을 제공했습니다. 십진수는 정의 가능한 정밀도를 가지며 제곱근 지원을 갖습니다. 루프 수에 따라 정확도를 보수적으로 추정하여 정확도를 설정했습니다.

최신 정보

골프를 치르면서 정확성과 속도를 향상시키기 위해 프로그램을 업데이트했습니다. 십진법을 사용하고 사용법을으로 sqrt()바꾸면 이제 200 배 빠릅니다. 이는 이제 6.5 시간 안에 백만 자리 결과를 제공하는 20 개의 루프를 계산할 수 있음을 의미합니다. 십진수는 종종 마지막 자릿수 (정밀도 한계에 대한 조작으로 인해)에 오류가 있으므로 프로그램은 이제 5 자리를 더 사용하고 버려 정확한 자릿수 만 인쇄합니다.x**2x*x

from decimal import*
d=Decimal
e=input()
getcontext().prec=5+(1<<e)
k=d(1)
j=d(2)
g=j*j
h=k/j
a=k
b=k/j.sqrt()
t=k/g
p=k
for i in[0]*e:f=a;a,b=(a+b)/j,(a*b).sqrt();c=f-a;t-=c*c*p;p+=p
l=a+b
print str(l*l/g/t)[:-5]

샘플 실행 :

$ echo 1 | python min.py 
3.1
$ echo 2 | python min.py 
3.141
$ echo 3 | python min.py 
3.1415926
$ echo 5 | python min.py 
3.1415926535897932384626433832795
$ echo 12 | python min.py
3.141592653589793238462643383279502884197169399375105820974944592307816406286208
99862803482534211706798214808651328230664709384460955058223172535940812848111745
02841027019385211055596446229489549303819644288109756659334461284756482337867831
65271201909145648566923460348610454326648213393607260249141273724587006606315588
17488152092096282925409171536436789259036001133053054882046652138414695194151160
94330572703657595919530921861173819326117931051185480744623799627495673518857527
24891227938183011949129833673362440656643086021394946395224737190702179860943702
77053921717629317675238467481846766940513200056812714526356082778577134275778960
91736371787214684409012249534301465495853710507922796892589235420199561121290219
60864034418159813629774771309960518707211349999998372978049951059731732816096318
59502445945534690830264252230825334468503526193118817101000313783875288658753320
83814206171776691473035982534904287554687311595628638823537875937519577818577805
32171226806613001927876611195909216420198938095257201065485863278865936153381827
96823030195203530185296899577362259941389124972177528347913151557485724245415069
59508295331168617278558890750983817546374649393192550604009277016711390098488240
12858361603563707660104710181942955596198946767837449448255379774726847104047534
64620804668425906949129331367702898915210475216205696602405803815019351125338243
00355876402474964732639141992726042699227967823547816360093417216412199245863150
30286182974555706749838505494588586926995690927210797509302955321165344987202755
96023648066549911988183479775356636980742654252786255181841757467289097777279380
00816470600161452491921732172147723501414419735685481613611573525521334757418494
68438523323907394143334547762416862518983569485562099219222184272550254256887671
79049460165346680498862723279178608578438382796797668145410095388378636095068006
42251252051173929848960841284886269456042419652850222106611863067442786220391949
45047123713786960956364371917287467764657573962413890865832645995813390478027590
09946576407895126946839835259570982582262052248940772671947826848260147699090264
01363944374553050682034962524517493996514314298091906592509372216964615157098583
87410597885959772975498930161753928468138268683868942774155991855925245953959431
04997252468084598727364469584865383673622262609912460805124388439045124413654976
27807977156914359977001296160894416948685558484063534220722258284886481584560285
06016842739452267467678895252138522549954666727823986456596116354886230577456498
03559363456817432411251507606947945109659609402522887971089314566913686722874894
05601015033086179286809208747609178249385890097149096759852613655497818931297848
21682998948722658804857564014270477555132379641451523746234364542858444795265867
82105114135473573952311342716610213596953623144295248493718711014576540359027993
44037420073105785390621983874478084784896833214457138687519435064302184531910484
81005370614680674919278191197939952061419663428754440643745123718192179998391015
91956181467514269123974894090718649423196156794520809514655022523160388193014209
37621378559566389377870830390697920773467221825625996615014215030680384477345492
02605414665925201497442850732518666002132434088190710486331734649651453905796268
56100550810665879699816357473638405257145910289706414011097120628043903975951567
71577004203378699360072305587631763594218731251471205329281918261861258673215791
98414848829164470609575270695722091756711672291098169091528017350671274858322287
18352093539657251210835791513698820914442100675103346711031412671113699086585163
98315019701651511685171437657618351556508849099898599823873455283316355076479185
35893226185489632132933089857064204675259070915481416549859461637180270981994309
92448895757128289059232332609729971208443357326548938239119325974636673058360414
28138830320382490375898524374417029132765618093773444030707469211201913020330380
19762110110044929321516084244485963766983895228684783123552658213144957685726243
34418930396864262434107732269780280731891544110104468232527162010526522721116603
96665573092547110557853763466820653109896526918620564769312570586356620185581007
29360659876486117

ungolfed 코드 :

from decimal import *
d = Decimal

loops = input()
# this is a conservative estimate for precision increase with each loop:
getcontext().prec = 5 + (1<<loops)

# constants:
one = d(1)
two = d(2)
four = two*two
half = one/two

# initialise:
a = one
b = one / two.sqrt()
t = one / four
p = one

for i in [0]*loops :
    temp = a;
    a, b = (a+b)/two, (a*b).sqrt();
    pterm = temp-a;
    t -= pterm*pterm * p;
    p += p

ab = a+b
print str(ab*ab / four / t)[:-5]

4
Hehhalf = one/two
Digital Trauma

올바른 자릿수를 인쇄하지 않은 것 같습니다. 그리고 속도 저하가 불필요한 사용으로 인한 것인지 궁금합니다 **.
aditsu

1
@aditsu, 나는 정확도를 예상 숫자로 줄였습니다 (그러나 반복에서 완벽하게 좋은 정확도를 버리는 것은 치아를 가려워합니다). **효과 에 대한 좋은 제안 . 나는 그들을 제거함으로써 많은 속도를 발견했다. 나는 1 시간에 20 루프를 만날 수 없습니다. 아마도 pypy 또는 Cython을 사용합니까? 흠. 나는 그것을 고려할 것이다.
논리 기사

훨씬 더 나은 :)이 문제의 경우, 좋은 정확도를 버리는 것은 나쁜 정확도를 유지하는 것보다 덜 악합니다. 1 시간 제한은 java 8에서 실행되는 cjam / java 테스트 코드를 기반으로합니다. 파이썬에는 많은 수 (Karatsuba & co)에 대한 효율적인 곱셈 / 나눗셈 / sqrt가 없을까요?
aditsu

@aditsu : 정수 에는 가라 쓰바가 있다고 생각 하지만 64 비트 사지 크기가 아니라 32 비트 사지 크기입니다. 십진법을 아는 사람.

5

파이썬 (2.7)-131 바이트

from gmpy import*
n=input()
p=a=fsqrt(mpf(8,4<<n));b=0
exec"a=fsqrt(a/2);b=1/(a-a*b+b/a+1);p*=b+a*a*b;a+=1/a;"*n
print`p`[5:2**n+6]

업데이트 : 이제 gmpy보다는을 사용 gmpy2합니다. 어떤 이유로 든 gmpy2단일 값으로 정밀도를 설정한다고해서 다른 값으로 전파되지는 않습니다. 계산 결과는 현재 컨텍스트의 정밀도로 되돌아갑니다. 정밀도가에 전파되어 gmpy나에게 더 직관적 인 것처럼 보입니다. 또한 덜 장황하다.

Borwein과 Borwein이 고안 한 많은 알고리즘 중 하나를 사용하여 약간 리팩터링했습니다. 내 상자에서 n = 20은 약 11 초가 걸립니다. 가장 효율적인 방법은 아니지만 여전히 나쁘지 않습니다.


리팩토링

원래 알고리즘은 다음과 같습니다.




리팩토링은 점진적으로 수행되었지만 최종 결과는




주요 단순화는 p n + 1 에서 발생합니다 . 또한 부서를 제거했기 때문에 약간 더 빠릅니다.

현재 구현 푸시 N을 다시 계산 한 반복 페이지 N + 1 의 다른 초기화 허용 P 0 ( 2√2를 )하지만, 그와 동일하다.


샘플 사용법

$ echo 1 | python pi-borwein.py
3.1

$ echo 2 | python pi-borwein.py
3.141

$ echo 5 | python pi-borwein.py
3.1415926535897932384626433832795

$ echo 10 | python pi-borwein.py
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198938095257201065485863278

훌륭하지만 n = 7에 대한 숫자가 없습니다.
aditsu

또한 이 알고리즘 입니까?
aditsu

@aditsu는 고쳤습니다.
primo

이제 마지막 자리는 n = 5에 잘못되었습니다.
aditsu

1
@aditsu pip install gmpy는 나를 위해 일했습니다. gmpy그리고 gmpy2별도의 패키지입니다. 그러나 더 이상 사용되지 않는에 의존합니다 distutils.
primo

3

BC와 뉴턴의 방법, 43 바이트

함수의 0을 찾는 뉴턴의 방법 은 2 차적으로 수렴되며 알고리즘은 Gauss-Legendre보다 훨씬 간단합니다. 기본적으로 다음과 같이 요약됩니다.

xnew = xold-f (xold) / f '(xold)

따라서 여기에 나온 스 니펫이 있습니다.

n=20;x=3;scale=2^n;while(n--)x-=s(x)/c(x);x

좀 더 읽기 쉽다 :

/* desired number of iterations */
n = 20;

/* starting estimate for pi */
x = 3;

/* set precision to 2^n */
scale = 2^n;

/* perform n iteration steps */
while(n--)
  // f:=sin, f'=cos
  x -= s(x)/c(x)

이를 테스트하려면 bc -l쉘에서 실행 하고 위의 스 니펫을 붙여 넣으십시오. 잠시 기다릴 준비를하십시오. n=20지금 약 5 분 동안 달리고 있으며 아직 끝나지 않았습니다. n=10약 40 초가 걸립니다.


4
사인과 코사인이 "덧셈, 뺄셈, 곱셈, 나눗셈 및 제곱 (근을 포함하여)과 같은 기본 연산"으로 적합한 지 확실하지 않습니다 . 그러나 자신의 사인 / 코사인을 굴려도 괜찮을 것입니다.
primo

1
그러나 깔끔한 공식-π는 f (x) = x-tan (x)의 고정 소수점이라고합니다.
Casey Chu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.