2011-01-19 31 views
7

Tôi đã triển khai loạt Madhava – Leibniz để tính pi trong Python, và sau đó trong Cython để cải thiện tốc độ. Phiên bản Python:Tính toán của Cython là không chính xác

from __future__ import division 
pi = 0 
l = 1 
x = True 
while True: 
    if x: 
     pi += 4/l 
    else: 
     pi -= 4/l 
    x = not x 
    l += 2 
    print str(pi) 

phiên bản Cython:

cdef float pi = 0.0 
cdef float l = 1.0 
cdef unsigned short x = True 
while True: 
    if x: 
     pi += 4.0/l 
    else: 
     pi -= 4.0/l 
    x = not x 
    l += 2 
    print str(pi) 

Khi tôi dừng lại phiên bản Python nó đã tính toán một cách chính xác pi để 3.141592. Phiên bản Cython cuối cùng đã kết thúc tại 3.141597 với một số chữ số hơn mà tôi không nhớ (thiết bị đầu cuối của tôi bị rơi) nhưng không chính xác. Tại sao tính toán của phiên bản Cython không chính xác?

Trả lời

18

Bạn đang sử dụng float trong phiên bản Cython - đó là single precision! Sử dụng double thay vào đó, tương ứng với float của Python (đủ thú vị). Loại C float chỉ có khoảng 8 chữ số thập phân đáng kể, trong khi double hoặc float của Python có khoảng 16 chữ số.

-1

Làm thế nào để bạn biết khi nào nó kết thúc? Bạn đã xem xét rằng giá trị cho pi sẽ dao động về giá trị thực, và bạn sẽ mong đợi rằng nếu bạn đã dừng mã tại một số điểm, bạn có thể có một giá trị quá cao (hoặc quá thấp)?

0

Nếu bạn muốn tăng tốc độ, lưu ý rằng bạn có thể đơn giản hóa logic bởi unrolling vòng lặp của bạn một lần, như vậy:

cdef double pi = 0.0 
cdef double L = 1.0 

while True: 
    pi += 4.0/L - 4.0/(L+2.0) 
    L += 4.0 
    print str(pi) 

Cũng lưu ý rằng bạn không cần phải gọi in bên trong vòng lặp - nó có lẽ dài gấp mười lần so với phần còn lại của phép tính.

Các vấn đề liên quan