Tính toán các chữ số rút gọn tổng các quyền hạn của pi


12

Cho một số nguyên dương n đầu ra tổng của n chữ số thập phân đầu tiên của phần phân số của π n .

Ví dụ đầu vào và đầu ra:

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

Các hàm tích hợp tính toán các chữ số của số pi hoặc đánh giá chuỗi lũy thừa hoặc phân số tiếp tục không được phép. Tiêu chuẩn áp dụng. Đầu vào / đầu ra có thể ở một định dạng thuận tiện (stdin, stdout, function in / output, v.v.).

ngắn nhất trong byte thắng.


Các hàm trig khác có thể được sử dụng để tính pi, nhưng không nhất thiết trực tiếp, như logarit hoặc logarit tưởng tượng cũng bị cấm? Ngoài ra, có giới hạn trên cho n mà nó có thể thất bại sau không?
FryAmTheEggman

@FryAmTheEggman Nếu các hàm trig đó có thể tính các chữ số tùy ý của pi, thì có, chúng bị cấm. Chương trình của bạn sẽ hoạt động trên lý thuyết cho mọi n , nhưng nó được tha thứ nếu thời gian chạy hoặc bộ nhớ trở nên quá cao.
orlp

Câu trả lời:


4

Python - 191 byte

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 phiên bản nhanh hơn - 206 byte

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]))

Đầu vào được lấy từ stdin. Đầu ra cho n = 5000 mất khoảng 14 giây với tập lệnh thứ hai (hoặc 60 giây với tập đầu tiên).


Sử dụng mẫu:

$ 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

Công thức được sử dụng là như sau:

Trong đó A nSố luân phiên thứ n , có thể được định nghĩa chính thức là số hoán vị xen kẽ trên một tập hợp kích thước n (xem thêm: A000111 ). Ngoài ra, chuỗi có thể được định nghĩa là thành phần của Số tiếp tuyến và Số bí mật ( A 2n = S n , A 2n + 1 = T n ), nhiều hơn về sau.

Hệ số hiệu chỉnh nhỏ c n nhanh chóng hội tụ đến 1 khi n trở nên lớn và được đưa ra bởi:

Với n = 1 , số tiền này để đánh giá Sê-ri Leibniz . Xấp xỉ π như 10 ½ , số lượng các điều khoản cần thiết có thể được tính như sau:

mà hội tụ (làm tròn lên) đến 17 , mặc dù các giá trị nhỏ hơn của n yêu cầu nhiều hơn đáng kể.

Để tính toán A n, có một số thuật toán và thậm chí là một công thức rõ ràng, nhưng tất cả chúng đều là bậc hai theo n . Ban đầu tôi đã mã hóa việc triển khai Thuật toán của Seidel , nhưng nó trở nên quá chậm để không thực tế. Mỗi lần lặp lại yêu cầu một thuật ngữ bổ sung được lưu trữ và các thuật ngữ tăng cường độ rất nhanh (loại "sai" của O (n 2 ) ).

Kịch bản đầu tiên sử dụng triển khai thuật toán ban đầu được đưa ra bởi Knuth và Buckholtz :

Đặt T 1, k = 1 với mọi k = 1..n

Các giá trị tiếp theo của T được đưa ra bởi mối quan hệ lặp lại:

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

A n sau đó được cho bởi T n, 1

(xem thêm: A185414 )

Mặc dù không được nêu rõ ràng, thuật toán này tính toán đồng thời cả Số tiếp tuyến và Số bí mật. Kịch bản thứ hai sử dụng một biến thể của thuật toán này bởi Brent và Zimmermann , tính toán T hoặc S , tùy thuộc vào tính chẵn lẻ của n . Sự cải thiện là bậc hai theo n / 2 , do đó cải thiện tốc độ ~ 4x.


1
Giải thích tuyệt vời về toán học đằng sau câu trả lời của bạn.
Logic Knight

3

Python 2, 246 byte

Tôi đã thực hiện một cách tiếp cận tương tự với câu trả lời của tôi tại Tính toán π với sự hội tụ bậc hai . Dòng cuối cùng lấy sức mạnh thứ N của pi và tính tổng các chữ số. Thử nghiệm N = 5000 mất một phút hoặc lâu hơn.

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]))

Một số xét nghiệm:

$ 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

Mã không mã hóa:

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]))

Dòng 8, bạn có thể tắt a=jp=jđể a=p=jiirc. Có lẽ.
Elias Benevedes

Cảm ơn. Có nhiều tối ưu hóa chơi gôn hơn cho mã này, nhưng nó sẽ không thể cạnh tranh nếu không viết lại bằng thuật toán không có Decimal.
Hiệp sĩ logic

1

Bình thường, 33

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

Dựa trên câu trả lời này của isaacg . Có lẽ có thể được chơi golf nhiều hơn. Chậm.

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
Câu trả lời này thực sự cần ít nhất là lời giải thích đủ để biện minh rằng nó tính đủ các chữ số để có câu trả lời đúng.
Peter Taylor

@PeterTaylor Tôi sẽ thêm một lời giải thích vào ngày mai, sắp đi ngủ.
orlp

Mỗi lần lặp tạo ra một bit đúng (xem Phụ lục A ). 2n chữ số cần lặp lại ~ 6,64n.
primo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.