2015-12-06 13 views
5

(Nếu câu trả lời thực sự là cách R sử dụng số nhị phân để lưu trữ số thập phân nhỏ, vẫn muốn biết chi tiết về lý do tại sao điều này xảy ra từ ai đó có kiến ​​thức về điều này)Tại sao R thực hiện không chính xác tổng ở đây?

Tôi đang sử dụng R để tính tổng, cụ thể cái này:

enter image description here

đây là mã R của tôi:

r = 21 #Number of times the loop executes 
n = 52 
sum = 0 #Running total 
for(k in 0:r){ 
    sum = sum + (1-(choose(2^(k), n)*(factorial(n)/(2^(n*k))))) 
    print(sum) 
} 

Nếu bạn nhìn vào kết quả, bạn sẽ nhận thấy:

[1] 1 
[1] 2 
... 
[1] 11.71419 
[1] 11.71923 
[1] 11.72176 
[1] 12.72176 
[1] 13.72176 

Tại sao nó bắt đầu tăng thêm 1 sau lần lặp thứ 19?

Có các công cụ tính toán tự do nào khác có thể phù hợp hơn với nhiệm vụ này không?

+2

Vì thuật ngữ sau 1- là 0 sau k = 19 và NaN (tràn) sau 25. Bạn mong đợi số tiền cần làm như thế nào? Hội tụ với điều gì đó hữu hạn? –

+2

Bạn có thể thử Maple, nó tìm thấy tổng số là khoảng 11.72428812. Trong điều khoản của R, một khả năng là làm mô phỏng Monte Carlo cho biến ngẫu nhiên T. – Julius

+3

Chỉ cho bản ghi, như được viết vòng lặp thực hiện r + 1 lần (không r lần, như được chỉ ra trong chú thích) –

Trả lời

5

Tất cả tính toán đang sử dụng số dấu phẩy động ở đây, thường không phù hợp với giai thừa và tăng quyền hạn (vì các giá trị này nhanh chóng rất lớn khiến tính toán kém chính xác hơn).

Hãy thử:

> factorial(52)/(2^(52*19)) 
[1] 3.083278e-230 
> factorial(52)/(2^(52*20)) 
[1] 0 

và so sánh với Pari-GP:

? \p 256 
realprecision = 269 significant digits (256 digits displayed) 
? precision((52!)/2^(52*19) + . , 24) 
%1 = 3.08327794368108826958435659488643289724 E-230 
? precision((52!)/2^(52*20) + . , 24) 
%2 = 6.8462523287873017654100595727727116496 E-246 
5

Nếu bạn đang tìm kiếm một cách để có được xung quanh tràn/vấn đề underflow bạn gặp, bạn có thể sử dụng nhật ký (để giữ cho các độ lớn hợp lý cho các phép tính trung gian) và sau đó tăng dần ở cuối:

options(digits=20) 

for(k in 0:r){ 
    sum = sum + (1 - exp(lchoose(2^k, n) + log(factorial(n)) - k*n*log(2))) 
    print(paste0(k,": ",sum)) 
} 

[1] "0: 1" 
[1] "1: 2" 
[1] "2: 3" 
... 
[1] "19: 11.7217600143979" 
[1] "20: 11.7230238079842" 
[1] "21: 11.7236558993777" 

Để kiểm tra xem điều này có đúng hay không, tôi đã chạy tổng kết ban đầu (không lấy nhật ký) trong Mathematica và nhận được kết quả tương tự với 12 chữ số thập phân.

Mặc dù bạn có thể khắc phục sự cố trong R, nếu bạn muốn sử dụng hệ thống đại số máy tính (cho phép bạn thực hiện phép tính biểu tượng và tính toán chính xác), Sage là nguồn mở và miễn phí.

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