IEEE754 richiede che i NaN non siano ordinati; minore di, maggiore di, uguale ecc. dovrebbe restituire tutti falso quando uno o entrambi gli operandi sono NaN.Le ottimizzazioni VC++ interrompono il confronto con NaN?
L'esempio riportato di seguito si ottiene la corretta F F F F F T
come previsto quando compilato utilizzando g ++ a tutti i livelli di ottimizzazione, e quando compilato utilizzando cl.exe (versione a 32 bit 15.00.30729.01) VC++ s 'senza argomenti di ottimizzazione o qualsiasi combinazione di/od,/fp: fast,/arch: SSE.
Tuttavia, quando compilato con/O1 o/O2 (e qualsiasi/nessun altro argomento di ottimizzazione), i risultati T T F F F T
, anche con/Op anche specificato.
La versione a 64 bit di cl.exe produce molte varianti - T T F F F T
, T T T F F T
, T T T F F F
etc - a seconda del livello di ottimizzazione e se/fp: veloce è specificato, ma come con la versione a 32 bit, un comportamento compatibile sembra solo per essere possibile con tutte le ottimizzazioni disabilitate.
Sto facendo qualche errore evidente? C'è un modo per far sì che il compilatore rispetti gli standard qui senza sacrificare tutte le altre ottimizzazioni?
#include <limits>
#include <stdio.h>
int main(int argc, char const ** argv)
{
float test = std::numeric_limits<float>::quiet_NaN();
printf("%c %c %c %c %c %c\n",
(test < test) ? 'T' : 'F',
(test <= test) ? 'T' : 'F',
(test == test) ? 'T' : 'F',
(test > test) ? 'T' : 'F',
(test >= test) ? 'T' : 'F',
(test != test) ? 'T' : 'F'
);
return 0;
}
Un esempio build.cmd
che riproduce il problema:
set "PATH=c:\program files (x86)\Microsoft Visual Studio 9.0\VC\bin\amd64;c:\program files (x86)\Microsoft Visual Studio 9.0\Common7;c:\program files (x86)\Microsoft Visual Studio 9.0\Common7\IDE"
set "LIB=c:\program files (x86)\microsoft visual studio 9.0\vc\lib\x64;c:\program files\Microsoft SDKs\Windows\v6.0A\Lib\x64"
cl test.cpp /fp:fast /Od /c /I "c:\program files (x86)\microsoft visual studio 9.0\vc\include"
link "/LIBPATH:C:/Program Files (x86)/Microsoft Visual Studio 9.0/vc/lib/amd64" "/LIBPATH:C:\Program Files\Microsoft SDKs\Windows\v6.0A\/Lib/x64" /DEBUG /IGNORE:4199 /IGNORE:4221 /MACHINE:X64 /SUBSYSTEM:CONSOLE test.obj
test
EDIT
Per la cronaca, l'esempio originariamente riportati nella domanda utilizzato
inline float QNaN()
{
static int const QNaNValue = 0x7fc00000;
return *(reinterpret_cast<float const*>(&QNaNValue));
}
generare un NaN; come un numero di commenti e risposte sottolineano, questo è un comportamento indefinito, e la sua sostituzione con std :: numeric_limits :: quiet_NaN() ha effettivamente risolto il problema per alcune versioni del CL.exe a 32 bit
Sospetto che possa avere qualcosa a che fare con il comportamento indefinito causato dal trattare un oggetto 'int' come' float'. Hai provato '0.0/0.0' invece? –
La funzione QNaN ha un comportamento non definito. Hai provato [usando le strutture C++] (http://en.cppreference.com/w/cpp/types/numeric_limits/quiet_NaN) per ottenere invece un NaN? –
Questa è una falsa pista, temo (il problema originale che ho incontrato era piuttosto complesso di questo semplice esempio l'ho ristretto a). Ho modificato l'esempio per utilizzare la funzione di libreria standard suggerita nei commenti, i risultati sono invariati. – moonshadow