W MSVC domyślny tryb zmiennoprzecinkowy to precise (/fp:precise)
. Oznacza to, że optymalizator może dokonać pewnych optymalizacji, aby poprawić dokładność lub wydajność.
Spróbuj zmienić tryb na strict (/fp:strict)
. Spowoduje to, że kompilator będzie przestrzegać ścisłych reguł zmiennoprzecinkowych dotyczących zaokrąglania i takich.
(EDIT: strict (/fp:strict)
nie wydają się działać w tym przypadku ...)
Jeśli spojrzeć na demontażu zoptymalizowanej konstrukcji, można zobaczyć, że cała obliczeń została złożona i zoptymalizowany na zewnątrz.
push 5374 ; 000014feH
push 5374 ; 000014feH
push OFFSET [email protected][email protected][email protected]
call DWORD PTR __imp__printf
add esp, 12 ; 0000000cH
EDIT: To wygląda jak błąd kompilatora optymalizator mnie.
Pod strict (/fp:strict)
dodaje kod generuje różne wyniki:
float a = 411.00418f;
float b = 1.0f;
float c = 0.076279849f;
unsigned short result1 = (unsigned short)((float)((a-b)/c));
float d = (float)((a-b)/c);
unsigned short result2 = (unsigned short)(d);
wyjściowy:
5374, 5375
wyciągając (float)((a-b)/c)
do osobnego przypisania nie powinny wpływać na wyniki pod strict (/fp:strict)
.
Znam jeden z tych facetów, którzy pracują na optymalizator MSVC. Wyślę mu raport o błędzie.
Aktualizacja:
Oto ich odpowiedź:
Cześć Alex, dzięki za tym raporcie. Spróbuję to naprawić dla nadchodzącego wydania VC++ o numerze , ale może się nie uda.
FWIW, błąd nie reprodukować jeśli rzucisz/arch: SSE2, a ponieważ umożliwiają: SSE2/arch domyślnie do następnego VC++ zwolnić (https://connect.microsoft.com/VisualStudio/feedback/details/688736/compiler-generates-sse-instructions-without-arch-sse).
Domyślne zachowanie pokazuje, że ten błąd został naprawiony. Ale jeśli powrócisz do starego modelu FP (throw/arch: IA32), błąd może nadal być obecny.
Eric
Więc oni potwierdził to jako błąd.
Ustawiam "model zmiennoprzecinkowy" na "Ścisły (/ fp: ścisły)", a wynik jest taki sam. Czy tęskniłem za czymś tutaj? –
Też to zauważyłem. Próbuję to też rozgryźć. W zoptymalizowanej kompilacji optymalizator składa wszystkie obliczenia. Myślę, że * nie jest to zgodne ze ścisłym zachowaniem zaokrąglania. – Mysticial
W rzeczywistości mój projekt używa C++/CLI w vs2010, więc może to też dotyczy? –