2011-09-30 39 views
6

thể trùng lặp:
Is JavaScript's Math broken?
Why can't decimal numbers be represented exactly in binary?Sum của 3 biến: Hành vi lạ

Điều gì sẽ là kết quả của mã tiếp theo:

if(0.3 == (0.1 + 0.1 + 0.1)) 
{ 
     alert(true); 
} 
else 
{ 
     alert(false); 
} 

Thật là lạ, nhưng kết quả sẽ là sai.

Lý do là kết quả của

0,1 + 0,1 + 0,1

sẽ

0,30000000000000004

Làm thế nào có thể giải thích hành vi này?

+2

Xem http://stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represented-exactly-in-binary – mtrw

+1

Và, cụ thể hơn trong JavaScript, http://stackoverflow.com/questions/4088590/0-43-in-javascript-not-1-2-its-1-20000000002-what-happen –

+2

Có lẽ bạn nên làm theo lời khuyên trong phần Câu hỏi thường gặp và tìm kiếm trước khi hỏi một câu hỏi đã được hỏi một lần gazillion trước . – paxdiablo

Trả lời

2

Đó là lý do tương tự 1/3 + 1/3 + 1/3 có thể không cung cấp cho bạn biết chính xác 1 trong số thập phân. Nếu bạn sử dụng 1/3 là .33333333, thì 1/3 + 1/3 + 1/3 sẽ cung cấp cho bạn .9999999 không chính xác.

Trừ khi bạn biết chính xác những gì bạn đang làm, không so sánh các loại số nguyên không phải là bình đẳng.

1

Đó là do bản chất của các phao được lưu trữ trong máy tính. Không có thứ như một cách chính xác để lưu trữ một số dấu phẩy động tùy ý. Những gì bạn thường làm gì khi bạn so sánh nổi là để xem nếu sự khác biệt là nhỏ hơn so với một số epsilon số nhỏ, như thế này:

function equals(f1, f2){ 
    var epsilon = 0.00001; //arbitrary choice 
    return (f1-f2 < epsilon && f2-f1 < epsilon); 
} 

như vậy trong trường hợp của bạn, thay đổi if (0,3 == (0,1 + 0,1 + 0,1)) đến nếu (bằng 0,3, (0,1 + 0,1 + 0,1))

1

Điều bạn đang gặp phải là một lỗi làm tròn dấu phẩy động cơ bản.

Chúng tôi không thể đại diện chính xác 0,1 mà không có một số lỗi do bản chất của số nhị phân. WolframAlpha reports số thập phân 0.1 đến số nhị phân bằng nhau ~ 0.00011001100110011 ... Lưu ý cách nó không thể được biểu diễn một cách hữu hạn trong hệ thống số nhị phân? Điều này có nghĩa là chúng ta phải quyết định một điểm cắt để dừng tính toán con số này nếu không chúng ta sẽ ở đây mãi mãi.

Điều này giới thiệu lỗi. Và lỗi này đã tích lũy khi mã thêm các số cùng nhau, dẫn đến số lượng cực nhỏ được thêm vào cuối tổng của bạn. Điều này đảm bảo rằng tổng sẽ không bao giờ là chính xác 0,3, đó là những gì các thử nghiệm IF đang tìm kiếm.

Một số số thập phân, tuy nhiên, có thể được biểu diễn chính xác dưới dạng nhị phân, chẳng hạn như phân đoạn 0.5 = bin 0.1 và dec 0.25 = bin 0.01.

We can demonstrate this tương tự như mã ban đầu của bạn bằng cách sử dụng 0,5 = (0,25 + 0,25).


Để đọc thêm về điều này, tôi khuyên bạn nên The Floating-Point Guide.

Nó cung cấp tổng quan tốt về khái niệm về số dấu phẩy động và cách phát hiện lỗi trong phép tính. Ngoài ra còn có một phần trên Javascript thể hiện cách khắc phục các lỗi làm tròn mà bạn đang gặp phải.