Tại sao double.NaN không bằng chính nó?


82

Ai đó có thể giải thích điều này với tôi? Trong C # double.NaN không bằng double.NaN

bool huh = double.NaN == double.NaN; // huh = false
bool huh2 = double.NaN >= 0; // huh2 = false
bool huh3 = double.NaN <= 0; // huh3 = false

Tôi có thể so sánh hằng số nào với một double.NaN và nhận đúng?


12
Chỉ để giải thích huhs của bạn: NaN không bằng gì cả, thậm chí không bằng chính nó. Đây là theo định nghĩa. vi.wikipedia.org/wiki/NaN
— Falaina

2
Điều tôi cho là đáng tiếc là bối cảnh bị mất. Nếu chúng ta có hai giá trị nhân đôi và cả hai đều được gán giá trị NaN để biểu thị giá trị thực tế 1/0. Họ cần được bình đẳng, nhưng vì hoàn cảnh bị mất, họ đang đối xử như không bằng nhau
— Michael Meadows

13
chính xác về mặt toán học. Tại sao người ta nghĩ rằng một nan sẽ bằng nan khác? sqrt (-1)! = 1/0
— Gordon Gustafson,

2
Nó cũng giống như NULLtrong SQL
— shashwat

2
@MichaelMeadows 1/0 là Inf, không phải NaN.
— Jim Balter

Câu trả lời:


133

Nếu bạn tò mò, đây là những gì Double.IsNaNtrông giống như:

public static bool IsNaN(double d)
{
    return (d != d);
}

Vui vẻ hả?


11
Điều đó thật kỳ lạ. Nhưng sau đó một lần nữa, như vậy là lời tuyên bố của NaN:public const double NaN = (double) 1.0 / (double) 0.0;
— Fredrik Mork

5
@Fredik, @Erich: Phép chia theo Zero sẽ đưa ra kết quả inf (hoặc, + inf, -inf dựa trên các toán hạng), 0/0 (trong số những người khác) tạo ra NaN. Có một bảng tốt đẹp với các hoạt động đặc biệt / kết quả tại steve.hollasch.net/cgindex/coding/ieeefloat.html
— Torsten Marek

5
Để thêm vào sự nhầm lẫn, Object.equals (double.NaN, double.NaN) trả về true
— Román

2
@JimBalter Bạn đúng là nhận xét của tôi đã sai: nguồn tham khảo thực sự đang nói public const double NaN = (double)0.0 / (double)0.0; liên kết đến nguồn tham chiếu . Cảm ơn vì đã chỉ ra điều đó. Ngày lưu ý khác: là sai và nói dối là hai việc hoàn toàn khác nhau
— Fredrik Mork

1
Không chắc liệu điều này có chính xác không khi bạn đăng nó, nhưng IsNaN ngày nay được định nghĩa khác .
— Joe Amenta



10

Hành vi có mục đích. Lý do là NaN đại diện cho một cái gì đó không phải là một con số và vì vậy đó là một cách tổng hợp cho nhiều thứ.

Cách thích hợp để so sánh một thứ gì đó là NaN là sử dụng hàm IsNaN .



6

Có một chức năng chuyên biệt cho việc này:

double.IsNan(huh);

5

Sử dụng phương pháp "Double.IsNaN (value)" để kiểm tra điều kiện này.


3

Trên thực tế, bạn đã tìm ra cách để kiểm tra xem số dấu phẩy động IEEE-754 có phải là NaN hay không : đó là giá trị dấu phẩy động duy nhất (hoặc phạm vi giá trị, vì có một số NaN) đánh giá Falsenếu được so sánh với chính nó, tức là:

bool isNaN(double v) {
    return v != v;
}

Về cơ bản, phương thức Double.IsNaN có thể thực sự làm điều tương tự. Bạn vẫn nên sử dụng nó, bởi vì hành vi này khá ngạc nhiên đối với bất kỳ ai không biết về tiêu chuẩn FP.


2

Điều duy nhất mà chúng tôi biết về NaN là nó "Không phải là một con số". Điều đó không có nghĩa là nó có một giá trị có thể kết hợp với trạng thái của nó. Ví dụ:

∞ + (-∞) = NaN

0/0 = NaN

(∞ + (-∞)) <> (0/0)

Đây là một số C # để chứng minh

var infinity = 100d / 0;
var negInfinity = -100d / 0;

var notANumber = infinity + negInfinity;
Console.WriteLine("Negative Infinity plus Infinity is NaN: {0}", double.IsNaN(notANumber));

var notANumber2 = 0d / 0d;
Console.WriteLine("Zero divided by Zero is NaN: {0}", double.IsNaN(notANumber2));

Console.WriteLine("These two are not equal: {0}", notANumber == notANumber2);

2

Lý do Double.NaN != Double.NaNrất đơn giản:

Bạn có mong đợi 0/0để được giống như Math.Sqrt(-3)? Và giống như Math.Sqrt(-7)?

Có một lỗi trong C # theo ý kiến ​​của tôi, nơi Equals()không được ghi đè cho NaN.

Assert.IsTrue(Double.NaN != Double.NaN);
Assert.IsTrue(Double.NaN.Equals(Double.NaN));

Đồng thời

Assert.IsTrue(Double.PositiveInfinity == Double.NegativeInfinity);
Assert.IsTrue(Double.PositiveInfinity.Equals(Double.PositiveInfinity));
// same for Double.NegativeInfinity and Single

Sử dụng các hàm tĩnh cho Doublevà Single, ví dụ:

Double.IsNaN(value) && Double.IsInfinity(value);

Hoặc cụ thể hơn:

Double.IsPositiveInfinity(value);
Double.IsNegativeInfinity(value);

2

Toán tử Equality coi hai giá trị NaN là không bằng nhau. Nói chung, không thể sử dụng toán tử Double để so sánh Double.NaN với các giá trị Double khác, mặc dù các phương pháp so sánh (chẳng hạn như Equals và CompareTo ) có thể. xem các ví dụ dưới đây

Được tham chiếu từ msdn

class Program
{
    static void Main(string[] args)
    {
        Double i = Double.NaN;
        while (!i.Equals(i)) //this would be result in false
        //while(i != i) // this would result in true.
        {
            Console.WriteLine("Hello");
        }
    }
}

đây là .net fiddle cho tương tự.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.