การคำนวณตัวเลขที่ถูกตัดทอนจำนวนของพลังของ pi


12

กำหนดจำนวนเต็มบวกnการส่งออกรวมของแรกnตัวเลขทศนิยมของส่วนที่เป็นเศษส่วนของπ n

ตัวอย่างอินพุตและเอาต์พุต:

1 → 1
2 → 14
3 → 6
4 → 13
5 → 24
50 → 211
500 → 2305
5000 → 22852

ไม่อนุญาตให้ใช้ฟังก์ชันการคำนวณตัวเลขในตัวของπหรือประเมินอนุกรมกำลังหรือเศษส่วนต่อเนื่อง ช่องโหว่มาตรฐานใช้ อินพุต / เอาต์พุตสามารถอยู่ในรูปแบบที่สะดวก (stdin, stdout, ฟังก์ชันใน / เอาต์พุต ฯลฯ )

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


ฟังก์ชันตรีโกณอื่น ๆ ที่สามารถใช้ในการคำนวณ pi ได้ แต่ไม่จำเป็นโดยตรงเช่นอาร์กแทนเจนต์หรือลอการิทึมจินตภาพก็ถูกแบนเช่นกัน? นอกจากนี้ยังมีข้อ จำกัด สูงสุดที่ n ว่าจะล้มเหลวหลังจากที่?
FryAmTheEggman

@FryAmTheEggman หากฟังก์ชั่นตรีโกณมิติเหล่านั้นสามารถคำนวณตัวเลขตามอำเภอใจของ pi ได้แล้วใช่ว่าพวกเขาถูกแบน โปรแกรมของคุณควรทำงานในทางทฤษฎีสำหรับnใด ๆแต่จะได้รับการอภัยหากรันไทม์หรือหน่วยความจำสูงเกินไป
orlp

คำตอบ:


4

Python - 191 ไบต์

t=i=1L;k=n=input();f=2000*20**n;A=range(n+1)
for k in range(2,n):A=[(A[j-1]+A[j+1])*j>>1for j in range(n-k+1)];f*=k
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))

รุ่นเร็วขึ้น ~ 4x - 206 ไบต์

t=i=1L;k=n=input();f=2000*20**n;A=[0,1]+[0]*n
for k in range(1,n):
 f*=k
 for j in range(-~n/2-k+1):A[j]=j*A[j-1]+A[j+1]*(j+2-n%2)
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))

อินพุตถูกนำมาจาก stdin เอาต์พุตสำหรับn = 5000ใช้เวลาประมาณ 14 วินาทีด้วยสคริปต์ที่สอง (หรือ 60 วินาทีกับสคริปต์แรก)


ตัวอย่างการใช้งาน:

$ echo 1 | python pi-trunc.py
1

$ echo 2 | python pi-trunc.py
14

$ echo 3 | python pi-trunc.py
6

$ echo 4 | python pi-trunc.py
13

$ echo 5 | python pi-trunc.py
24

$ echo 50 | python pi-trunc.py
211

$ echo 500 | python pi-trunc.py
2305

$ echo 5000 | python pi-trunc.py
22852

สูตรที่ใช้มีดังต่อไปนี้:

ที่nเป็นn THสลับหมายเลขซึ่งสามารถกำหนดอย่างเป็นทางการเป็นจำนวนพีชคณิตสลับกับชุดของขนาดที่n (ดูเพิ่มเติมที่: A000111 ) อีกวิธีหนึ่งสามารถกำหนดลำดับเป็นองค์ประกอบของตัวเลขแทนเจนต์และตัวเลข Secant ( A 2n = S n , A 2n + 1 = T n ), เพิ่มเติมในภายหลัง

ปัจจัยการแก้ไขขนาดเล็กc nเข้าหา1อย่างรวดเร็วเมื่อnกลายเป็นใหญ่และได้รับจาก:

สำหรับn = ที่ 1จำนวนนี้เพื่อประเมินLeibniz ซีรีส์ ประมาณπเป็น10 ½จำนวนคำที่ต้องการสามารถคำนวณได้ดังนี้:

ซึ่งรวมกัน (ปัดขึ้น) ถึง17แม้ว่าค่าที่น้อยกว่าของn จะต้องการมากกว่านั้น

สำหรับการคำนวณของnมีขั้นตอนวิธีการหลายและแม้กระทั่งสูตรอย่างชัดเจน แต่ทั้งหมดของพวกเขากำลังสองโดยn ฉันเขียนโค้ดการใช้งานอัลกอริทึมของ Seidelแต่ดูเหมือนจะช้าเกินกว่าจะใช้งานได้จริง การวนซ้ำแต่ละครั้งจะต้องมีคำศัพท์เพิ่มเติมเพื่อจัดเก็บและข้อกำหนดเพิ่มขึ้นอย่างรวดเร็วมาก ( O "ผิด" ชนิดO (n 2 ) )

สคริปต์แรกใช้การนำไปใช้ของอัลกอริทึมที่ได้รับจากKnuth และ Buckholtz :

ให้ T 1, k = 1 สำหรับทุก k = 1..n

ค่าที่ตามมาของ T ถูกกำหนดโดยความสัมพันธ์ที่เกิดซ้ำ:

T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]

nจะได้รับแล้วโดย T n 1

(ดูเพิ่มเติมที่: A185414 )

แม้ว่าจะไม่ได้ระบุไว้อย่างชัดเจนอัลกอริทึมนี้จะคำนวณทั้งตัวเลขแทนเจนต์และตัวเลข Secant พร้อมกัน สคริปต์ที่สองใช้รูปแบบของขั้นตอนวิธีนี้โดยเบรนท์และซิมเมอซึ่งจะคำนวณทั้งTหรือSทั้งนี้ขึ้นอยู่กับความเท่าเทียมกันของn การปรับปรุงเป็นกำลังสองโดยn / 2ดังนั้นการปรับปรุงความเร็ว ~ 4x


1
คำอธิบายที่ดีเลิศของคณิตศาสตร์ที่อยู่เบื้องหลังคำตอบของคุณ
Logic Knight

3

Python 2, 246 ไบต์

ผมได้นำวิธีการคล้ายกับคำตอบของฉันที่πคำนวณกับลู่กำลังสอง บรรทัดสุดท้ายใช้กำลัง Nth ของ pi และผลรวมตัวเลข การทดสอบ N = 5,000 ใช้เวลาประมาณหนึ่งนาที

from decimal import*
d=Decimal
N=input()
getcontext().prec=2*N
j=d(1)
h=d(2)
f=h*h
g=j/h
a=j
b=j/h.sqrt()
t=j/f
p=j
for i in bin(N)[2:]:e=a;a,b=(a+b)/h,(a*b).sqrt();c=e-a;t-=c*c*p;p+=p
k=a+b
l=k*k/f/t
print sum(map(int,`l**N`.split('.')[1][:N]))

การทดสอบบางอย่าง:

$ echo 1 | python soln.py
1
$ echo 3 | python soln.py
6
$ echo 5 | python soln.py
24
$ echo 500 | python soln.py
2305
$ echo 5000 | python soln.py
22852

รหัสที่ไม่ดี

from decimal import *
d = Decimal

N = input()
getcontext().prec = 2 * N

# 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 bin(N)[2:] :
    temp = a;
    a, b = (a+b)/two, (a*b).sqrt();
    pterm = temp-a;
    t -= pterm*pterm * p;
    p += p

ab = a+b
pi = ab*ab / four / t
print sum(map(int, `pi ** N`.split('.')[1][:N]))

บรรทัดที่ 8 คุณสามารถเลี้ยวa=jและp=jไปยังa=p=jiirc ได้ อาจจะ.
Elias Benevedes

ขอบคุณ มีการเพิ่มประสิทธิภาพการเล่นกอล์ฟสำหรับรหัสนี้มากขึ้น แต่จะไม่สามารถแข่งขันได้หากไม่เขียนซ้ำโดยใช้อัลกอริทึมที่ไม่มีทศนิยม
Logic Knight

1

Pyth, 33

s<>j^u+/*GHhyHy^TyQr*TQ0ZQT_y*QQQ

ขึ้นอยู่กับคำตอบนี้โดย isaacg อาจจะเล่นกอล์ฟมากกว่านี้ ช้า.

s<>j            Digit sum of...
  ^                 
    u               Evaluate pi = 2 + 1/3*(2 + 2/5*(2 + 3/7*(2 + 4/9*(2 + ...))))
      +
        /
          *GH
          hyH
        y^TyQ       Except we generate a large integer containing 2n digits,
                    rather than a fraction.
      r*TQ0         Experimentally verified that 10*n iterations will give enough
                    precision for 2n digits (# digits correct grows faster than 2n).
      Z
    Q               To the nth power.
  T_y*QQQ         Get the last 2n^2 digits (all the fractional digits) and get the
                  first n fractional digits.

1
คำตอบนี้ต้องการคำอธิบายอย่างน้อยที่สุดเพียงพอที่จะพิสูจน์ว่ามันคำนวณตัวเลขที่เพียงพอเพื่อให้ได้คำตอบที่ถูกต้อง
Peter Taylor

@PeterTaylor ฉันจะเพิ่มคำอธิบายในวันพรุ่งนี้กำลังจะเข้านอน
orlp

การวนซ้ำแต่ละครั้งจะสร้างบิตที่ถูกต้องหนึ่งตัว (ดูภาคผนวก A ) ตัวเลข 2n ควรมีการทำซ้ำ ~ 6.64n
Primo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.