double.NaN - как работает эта нелогичная функция? - PullRequest
4 голосов
/ 25 декабря 2010

Я наткнулся на определение .NET double.NaN в коде:

public const double NaN = (double)0.0 / (double)0.0;

Это делается аналогично в PositiveInfinity и NegativeInfinity.

double.IsNaN (с удалением нескольких прагм и комментариев) определяется как:

[Pure] 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool IsNaN(double d) 
{
    if (d != d)
    { 
        return true; 
    }
    else 
    {
        return false;
    }
}

Это очень нелогично для меня.

Почему NaN определяется как деление на ноль? Как 0.0 / 0.0 представляется "за кадром"? Как деление на 0 возможно в double и почему NaN != NaN?

Ответы [ 3 ]

6 голосов
/ 25 декабря 2010

Довольно простой ответ здесь.В .Net Framework реализован стандарт с плавающей запятой, определенный IEEE (System.Double соответствует стандарту IEC 60559: 1989 (IEEE 754) для двоичной арифметики с плавающей запятой.) .Это связано с тем, что арифметика с плавающей запятой на самом деле должна работать во многих системах, а не только в архитектурах x86 / 64, поэтому следование соглашениям гарантирует, что проблем совместимости будет меньше (например, перенос кода из DSP в процессор x86)

Что касается d! = D, то это оптимизация производительности.В основном эта инструкция опирается на аппаратную инструкцию, которая может очень быстро определить, равны ли два двойных числа с плавающей запятой.По стандарту NAN! = NAN и, следовательно, это самый быстрый способ проверки.Пытаюсь найти для вас ссылку.

2 голосов
/ 25 декабря 2010

Почему NaN определяется как деление на нуль? Как деление на 0 может быть можно в два раза, и почему NaN ! = NaN?

Все это предписано стандартом IEEE 754, который в значительной степени реализуют все современные процессоры.

Как 0.0 / 0.0 представляется "за кадром"?

Имея показатель степени со всеми битами, установленными в 1, и мантиссу, в которой, по крайней мере, один бит установлен в 1. Обратите внимание, что это означает, что существует большое количество различных битовых комбинаций, которые все представляют NaN - но, как упоминалось выше, даже если битовые комбинации идентичны, их следует считать не равными (т. е. == должно возвращать false).

0 голосов
/ 25 декабря 2010

Из C # Spec:

14.9.2 Операторы сравнения с плавающей точкой Предопределенные операторы сравнения с плавающей точкой:

оператор bool == (с плавающей точкой x, с плавающей точкой y); оператор bool == (double x, double y);
оператор bool! = (float x, float y); оператор bool! = (double x, double y);
оператор bool <(float x, float y); оператор bool <(double x, double y); <br> оператор bool> (float x, float y); оператор bool> (double x, double y);
оператор bool <= (с плавающей точкой x, с плавающей точкой y); оператор bool <= (double x, double y); <br> оператор bool> = (с плавающей точкой x, с плавающей точкой y); оператор bool> = (double x, double y);

Операторы сравнивают операнды в соответствии с правилами стандарта МЭК 60559: Если любой из операндов равен NaN, результат равен false для всех операторов, кроме! =, Для которого этот результат равен true. Для любых двух операндов x! = Y всегда дает тот же результат, что и! у). Однако когда один или оба операнда имеют значение NaN, операторы <,>, <= и> = не дают таких же результатов, как логическое отрицание противоположного оператора. [Пример: если любой из x и y равен NaN, то x = y) верно. конец примера]

Что касается представления NaN за кулисами, в статье в википедии по спецификации IEEE есть несколько примеров.

...