2010-10-29 28 views
9

Ai đó có thể giải thích tại sao nhân với 100 ở đây mang lại kết quả kém chính xác nhưng nhân với 10 lần hai lần cho kết quả chính xác hơn?lỗi điểm nổi ruby ​​

± % sc 
Loading development environment (Rails 3.0.1) 
>> 129.95 * 100 
12994.999999999998 
>> 129.95*10 
1299.5 
>> 129.95*10*10 
12995.0 
+1

Rất có thể do biểu thị nhị phân của số dấu phẩy động. Bạn không thể viết chính xác 129,95 trong cơ sở 2 tôi giả định. –

+10

Liên kết bắt buộc: [Điều mà mỗi nhà khoa học máy tính cần biết về số học dấu chấm động] (http://docs.sun.com/source/806-3568/ncg_goldberg.html) –

+0

Bất kỳ manh mối nào tại sao điều này sẽ KHÔNG xảy ra cho tôi? Tôi đang cố gắng để chứng minh điều này, và tôi nhập 129,95 * 100 như trên vào IRB và tôi bất ngờ nhận được câu trả lời đúng. – Joel

Trả lời

22

Nếu bạn làm các tính toán bằng tay trong nhị phân đúp chính xác, đó là hạn chế đến 53 bit có ý nghĩa, bạn sẽ thấy những gì đang xảy ra:

129,95 = 1,0000001111100110011001100110011001100110011001100110 x 2^7

129,95 * 100 = 1.1001011000010111111111111111111111111111111111111111011 x 2^13

này dài 56 bit có ý nghĩa, vì vậy làm tròn lên 53 bit nó

1,10010110000101111111111111111111111111111111111111 11 x 2^13, bằng với

12994,999999999998181010596454143524169921875

Bây giờ 129,95 * 10 = 1.01000100110111111111111111111111111111111111111111111 x 2^10

Đây là 54 bit có ý nghĩa dài, do đó làm tròn lên 53 bit đó là 1,01000100111 x 2^10 = 1299.5

Bây giờ 1299.5 * 10 = 1.1001011000011 x 2^13 = 12995.

3

Trước tiên: bạn đang xem biểu diễn chuỗi của kết quả chứ không phải kết quả thực. Nếu bạn thực sự muốn so sánh hai kết quả, bạn nên định dạng cả hai kết quả một cách rõ ràng, sử dụng String#% và bạn nên định dạng cả hai kết quả theo cùng một cách.

Thứ hai, đó chỉ là cách các số dấu phẩy động nhị phân hoạt động. Chúng không chính xác, chúng hữu hạn và chúng là nhị phân. Tất cả ba có nghĩa là bạn nhận được làm tròn lỗi, mà nói chung nhìn hoàn toàn ngẫu nhiên, trừ khi bạn xảy ra để có ghi nhớ toàn bộ IEEE754 và có thể đọc nó ngược trong giấc ngủ của bạn.

2

Không có số dấu phẩy động chính xác bằng 129.95. Vì vậy, ngôn ngữ của bạn sử dụng một giá trị gần với nó thay thế. Khi giá trị đó được nhân với 100, kết quả là gần 12995, nhưng nó chỉ như vậy sẽ xảy ra không bằng 12995. (Nó cũng không chính xác bằng 100 lần giá trị ban đầu nó được sử dụng thay cho 129.95.) Vì vậy, thông dịch viên của bạn in một số thập phân gần (nhưng không bằng) giá trị của 129.95 * 100 và cho bạn thấy rằng nó không phải là chính xác 12995. Nó cũng chỉ như vậy sẽ xảy ra rằng kết quả 129.95 * 10 là chính xác bằng 1299.5. Điều này chủ yếu là may mắn.

Điểm mấu chốt là, không bao giờ mong đợi sự bình đẳng ra khỏi bất kỳ số học dấu phẩy động nào, chỉ "gần gũi".

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