Tôi là thành viên của ủy ban IEEE-754, tôi sẽ cố gắng giúp làm rõ mọi thứ một chút.
Trước hết, số dấu phẩy động không phải là số thực và số học dấu phẩy động không thỏa mãn các tiên đề của số học thực. Trichotomy không phải là tài sản duy nhất của số học thực sự không giữ cho phao, thậm chí không quan trọng nhất. Ví dụ:
- Ngoài ra không phải là kết hợp.
- Luật phân phối không giữ.
- Có số dấu phẩy động mà không đảo.
Tôi có thể tiếp tục. Không thể chỉ định loại số học có kích thước cố định thỏa mãn tất cả các thuộc tính của số học thực mà chúng ta biết và yêu thích. Ủy ban 754 phải quyết định bẻ cong hoặc phá vỡ một số trong số họ. Điều này được hướng dẫn bởi một số nguyên tắc khá đơn giản:
- Khi chúng ta có thể, chúng ta khớp với hành vi của số học thực sự.
- Khi không thể, chúng tôi cố gắng thực hiện các hành vi vi phạm như có thể dự đoán và dễ chẩn đoán nhất có thể.
Về nhận xét của bạn "điều đó không có nghĩa là câu trả lời đúng là sai", điều này là sai. Vị ngữ (y < x)
hỏi có y
nhỏ hơn không x
. Nếu y
là NaN, thì nó không nhỏ hơn bất kỳ giá trị dấu phẩy động nàox
, vì vậy câu trả lời nhất thiết là sai.
Tôi đã đề cập rằng trichotomy không giữ các giá trị dấu phẩy động. Tuy nhiên, có một tài sản tương tự mà giữ. Khoản 5.11, khoản 2 của tiêu chuẩn 754-2008:
Bốn quan hệ loại trừ lẫn nhau là có thể: ít hơn, bằng nhau, lớn hơn và không có thứ tự. Trường hợp cuối cùng phát sinh khi có ít nhất một toán hạng là NaN. Mỗi NaN sẽ so sánh không có thứ tự với tất cả mọi thứ, bao gồm cả chính nó.
Theo như viết mã bổ sung để xử lý NaN, thường có thể (mặc dù không phải lúc nào cũng dễ dàng) để cấu trúc mã của bạn theo cách mà NaN rơi đúng cách, nhưng điều này không phải lúc nào cũng đúng. Khi không, một số mã bổ sung có thể là cần thiết, nhưng đó là một cái giá nhỏ để trả cho sự tiện lợi mà việc đóng đại số mang lại cho số học dấu phẩy động.
Phụ lục: Nhiều nhà bình luận đã lập luận rằng sẽ hữu ích hơn khi duy trì tính phản xạ của sự bình đẳng và trichotomy với lý do áp dụng NaN! = NaN dường như không bảo tồn bất kỳ tiên đề quen thuộc nào. Tôi thú nhận có một số thiện cảm với quan điểm này, vì vậy tôi nghĩ rằng tôi sẽ xem lại câu trả lời này và cung cấp thêm một chút bối cảnh.
Sự hiểu biết của tôi khi nói chuyện với Kahan là NaN! = NaN bắt nguồn từ hai cân nhắc thực dụng:
Điều đó x == y
tương đương với x - y == 0
bất cứ khi nào có thể (ngoài việc là một định lý về số học thực, điều này làm cho việc thực hiện phần cứng so sánh hiệu quả hơn về mặt không gian, điều cực kỳ quan trọng tại thời điểm tiêu chuẩn được phát triển - tuy nhiên, điều này bị vi phạm cho x = y = vô cùng, vì vậy bản thân nó không phải là một lý do tuyệt vời; nó có thể bị uốn cong một cách hợp lý (x - y == 0) or (x and y are both NaN)
).
Quan trọng hơn, không có isnan( )
vị ngữ tại thời điểm NaN được chính thức hóa trong số học 8087; nó là cần thiết để cung cấp cho các lập trình viên một phương tiện thuận tiện và hiệu quả để phát hiện các giá trị NaN không phụ thuộc vào các ngôn ngữ lập trình cung cấp thứ gì isnan( )
đó có thể mất nhiều năm. Tôi sẽ trích dẫn bài viết của Kahan về chủ đề này:
Không có cách nào để loại bỏ NaN, chúng sẽ vô dụng như Indefinites trên CRAYs; ngay khi gặp phải, tính toán sẽ được dừng lại tốt nhất thay vì tiếp tục trong một thời gian không xác định cho một kết luận không xác định. Đó là lý do tại sao một số hoạt động khi NaN phải cung cấp kết quả không phải NaN. Hoạt động nào? Các trường hợp ngoại lệ là các biến vị ngữ C, x x == x và x x = = x, tương ứng là 1 và 0 cho mọi số x vô hạn hoặc hữu hạn x nhưng ngược lại nếu x không phải là số (NaN); những điều này cung cấp sự phân biệt ngoại lệ đơn giản duy nhất giữa NaN và số trong các ngôn ngữ thiếu một từ cho NaN và một vị từ IsNaN (x).
Lưu ý rằng đây cũng là logic loại trừ việc trả lại một cái gì đó giống như một Not Not A-Boolean. Có lẽ chủ nghĩa thực dụng này đã bị đặt sai chỗ, và tiêu chuẩn cần phải cóisnan( )
, nhưng điều đó sẽ khiến NaN gần như không thể sử dụng hiệu quả và thuận tiện trong vài năm trong khi thế giới chờ đợi áp dụng ngôn ngữ lập trình. Tôi không tin rằng đó sẽ là một sự đánh đổi hợp lý.
Nói thẳng ra: kết quả của NaN == NaN sẽ không thay đổi ngay bây giờ. Tốt hơn để học cách sống với nó hơn là phàn nàn trên internet. Nếu bạn muốn lập luận rằng mối quan hệ thứ tự phù hợp với các container cũng tồn tại, tôi khuyên bạn nên ủng hộ rằng ngôn ngữ lập trình yêu thích của bạn triển khai totalOrder
vị từ được chuẩn hóa trong IEEE-754 (2008). Thực tế là nó đã không nói lên tính hợp lệ của mối quan tâm của Kahan đã thúc đẩy tình trạng hiện tại.
while (fabs(x - oldX) > threshold)
, thoát khỏi vòng lặp nếu sự hội tụ xảy ra hoặc NaN đi vào tính toán. Phát hiện NaN và biện pháp khắc phục thích hợp sau đó sẽ xảy ra bên ngoài vòng lặp.