Сломанные сравнения NaN в x64 VS2019 - VS2015 - PullRequest
0 голосов
/ 22 января 2020

У меня есть простая программа:

#include <iostream>
#include <cmath>
int main()
{
    double dNan = std::nan("nan");
    double dNotNan = 3961.12345;

    if (dNan == dNotNan)
        std::cout << "Nan == Not Nan" << std::endl;
    else
        std::cout << "Nan != Not Nan" << std::endl;   
}

Скомпилировано с платформой x64 с "/ fp: fast", вывод:

Nan == Not Nan

С платформой x86 или / fp: точный выходное значение - ожидаемое «Nan! = Not Nan».

Сгенерированный для сравнения ассемблер:

00007FF6F8E7101F  ucomisd     xmm0,mmword ptr [__real@40aef23f34d6a162 (07FF6F8E732B8h)]  
00007FF6F8E71027  je          main+30h (07FF6F8E71030h)  

, где __real@40aef23f34d6a162 - значение 3961.12345, а xmm0 содержит NaN "0000000000000000-7FF8000000000000". Результатом команды UCOMISD является то, что все флаги ZP, CF, PF установлены, что указывает «неупорядоченный», то есть, по крайней мере, один из операндов является NaN. Инструкция JE проверяет только флаг ZF, который устанавливается в 1, когда два операнда равны.

В документации сказано: «Специальные значения (NaN, + infinity, -infinity, -0.0) могут не распространяться или вести себя строго в соответствии со стандартом IEEE-754 "с примером в другом месте, представленным как NaN - NaN = 0, но поведение сравнения, похоже, выходит за пределы" не строго по стандарту ".

Я не могу найти любая информация по этому вопросу; действительно ли это ожидаемое поведение или я только что обнаружил ошибку компилятора?

...