Чому double.NaN не дорівнює собі?


82

Хтось може пояснити мені це? У C # double.NaN не дорівнює double.NaN

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

Яку константу я можу порівняти з подвійним.NaN і здійснити?


12
Тільки для пояснення ваших ага: NaN не дорівнює нічому, навіть самому собі. Це за визначенням. en.wikipedia.org/wiki/NaN
Фалайна,

2
На жаль, на жаль, контекст втрачено. Якщо у нас було два подвійні, і обом було присвоєно значення NaN для того, щоб представити фактичне значення 1/0. Вони повинні бути рівними, але оскільки контекст втрачений, їх вважають не рівними
Майкл Медоус

13
математично правильний. Чому хтось думає, що один нан буде рівний іншому? sqrt (-1)! = 1/0
Гордон Густафсон

2
Це як NULLу SQL
shashwat

2
@MichaelMeadows 1/0 - це Inf, а не NaN.
Jim Balter

Відповіді:


133

Якщо вам цікаво, ось так Double.IsNaNвиглядає:

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

Фанки, так?


11
Це дивно добре. Але знову ж таки, так само заява NaN:public const double NaN = (double) 1.0 / (double) 0.0;
Фредрік Морк,

5
@Fredik, @Erich: Ділення за нулем дасть inf (або, + inf, -inf на основі операндів), 0/0 (серед інших) призводить до NaN. Є хороша таблиця зі спеціальними операціями / результати за адресою steve.hollasch.net/cgindex/coding/ieeefloat.html
Торстен Марек

5
Щоб додати плутанини, object.Equals (double.NaN, double.NaN) повертає true
Роман

2
@JimBalter Ви праві, що мій коментар був помилковим: джерело посилання насправді говорить про public const double NaN = (double)0.0 / (double)0.0; посилання на джерело посилання . Дякуємо, що вказали на це. З іншого боку: помилятися і брехати - це дві абсолютно різні речі
Фредрік Мерк,

1
Не впевнений, чи це було правильно, коли ви його розмістили, але IsNaN сьогодні визначається по-іншому .
Джо Амента



10

Поведінка навмисне. Причиною того, що NaN є щось, що не є числом, і є своєрідним загальним для багатьох речей.

Правильний спосіб порівняти щось із NaN - це використовувати функцію IsNaN .




5

Використовуйте метод "Double.IsNaN (value)", щоб перевірити наявність цього стану.


3

Насправді ви вже знайшли спосіб перевірити, чи є число з плаваючою точкою IEEE-754 NaN : це єдине значення з плаваючою точкою (або діапазон значень, оскільки існує кілька NaN), яке оцінює, Falseякщо порівнювати з самим собою, тобто:

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

Під капотом метод Double.IsNaN може насправді робити те саме. Ви все одно повинні ним користуватися, оскільки поведінка є досить дивною для тих, хто не знає про стандарт FP.


2

Єдине, що ми знаємо про NaN, це те, що це "не число". Це не означає, що він має цінність, яка пов'язана зі своїм станом. Наприклад:

∞ + (-∞) = NaN

0/0 = NaN

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

Ось декілька C # для демонстрації

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

Причина Double.NaN != Double.NaNпроста:

Ви очікуєте 0/0бути таким самим, як Math.Sqrt(-3)? І те саме, що Math.Sqrt(-7)?

На мій погляд, є помилка в C #, Equals()яка не перевизначена для NaN.

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

В той самий час

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

Використовуйте статичні функції для Doubleі Single, наприклад

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

Або більш конкретно:

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

2

Оператор рівності вважає два значення NaN нерівними одне одному. Загалом, Подвійні оператори не можуть бути використані для порівняння з іншими Double.NaN подвійних значень, хоча методи порівняння (наприклад, рівних і CompareTo ) може. дивіться приклади нижче

Посилання з 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");
        }
    }
}

ось скрипка .net для того самого.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.