本文翻譯自:Why does NaN - NaN == 0.0 with the Intel C++ Compiler?
It is well-known that NaNs propagate in arithmetic, but I couldn't find any demonstrations, so I wrote a small test:
衆所周知,NaNs在算術中傳播,但我找不到任何示範,是以我寫了一個小測試:#include <limits>
#include <cstdio>
int main(int argc, char* argv[]) {
float qNaN = std::numeric_limits<float>::quiet_NaN();
float neg = -qNaN;
float sub1 = 6.0f - qNaN;
float sub2 = qNaN - 6.0f;
float sub3 = qNaN - qNaN;
float add1 = 6.0f + qNaN;
float add2 = qNaN + qNaN;
float div1 = 6.0f / qNaN;
float div2 = qNaN / 6.0f;
float div3 = qNaN / qNaN;
float mul1 = 6.0f * qNaN;
float mul2 = qNaN * qNaN;
printf(
"neg: %f\nsub: %f %f %f\nadd: %f %f\ndiv: %f %f %f\nmul: %f %f\n",
neg, sub1,sub2,sub3, add1,add2, div1,div2,div3, mul1,mul2
);
return 0;
}
The example ( running live here ) produces basically what I would expect (the negative is a little weird, but it kind of makes sense):
這個例子( 在這裡運作 )基本上産生了我所期望的(負面有點奇怪,但它有點意義):neg: -nan
sub: nan nan nan
add: nan nan
div: nan nan nan
mul: nan nan
MSVC 2015 produces something similar.
MSVC 2015産生類似的東西。However, Intel C++ 15 produces:
但是,英特爾C ++ 15産生:neg: -nan(ind)
sub: nan nan 0.000000
add: nan nan
div: nan nan nan
mul: nan nan
Specifically,
qNaN - qNaN == 0.0
.
具體來說,qNaN - qNaN == 0.0
。 This... can't be right, right?
這......不可能是對的,對嗎?What do the relevant standards (ISO C, ISO C++, IEEE 754) say about this, and why is there a difference in behavior between the compilers?
相關标準(ISO C,ISO C ++,IEEE 754)對此有何評論,為什麼編譯器之間的行為存在差異?#1樓
參考:https://stackoom.com/question/2B5dV/為什麼NaN-NaN-與英特爾C-編譯器
#2樓
The default floating point handling in Intel C++ compiler is
/fp:fast
, which handles
NaN
's unsafely (which also results in
NaN == NaN
being
true
for example).
英特爾C ++編譯器中的預設浮點處理是/fp:fast
,它不安全地處理 NaN
(例如,這也導緻 NaN == NaN
為 true
)。 Try specifying
/fp:strict
or
/fp:precise
and see if that helps.
嘗試指定/fp:strict
或 /fp:precise
,看看是否有幫助。 #3樓
This .
這個 。.
。.
。can't be right, right?
不能對,對吧?My question: what do the relevant standards (ISO C, ISO C++, IEEE 754) say about this?
我的問題:相關标準(ISO C,ISO C ++,IEEE 754)對此有何看法?Petr Abdulin already answered why the compiler gives a
0.0
answer.
Petr Abdulin已經回答了編譯器給出0.0
答案的原因。 Here is what IEEE-754:2008 says:
以下是IEEE-754:2008所說的内容:(6.2 Operations with NaNs) "[...] For an operation with quiet NaN inputs, other than maximum and minimum operations, if a floating-point result is to be delivered the result shall be a quiet NaN which should be one of the input NaNs." (6.2使用NaN的操作)“[...]對于具有安靜NaN輸入的操作,除了最大和最小操作之外,如果要傳遞浮點結果,結果應該是一個安靜的NaN,它應該是一個輸入NaN。“
So the only valid result for the subtraction of two quiet NaN operand is a quiet NaN;
是以減去兩個安靜的NaN操作數的唯一有效結果是一個安靜的NaN;any other result is not valid.
任何其他結果無效。The C Standard says:
C标準說:(C11, F.9.2 Expression transformations p1) "[...] (C11,F.9.2表達式轉換p1)“[...] x − x → 0. 0 "The expressions x − x and 0. 0 are not equivalent if x is a NaN or infinite" x - x→0。0“如果x是NaN或無窮大,則表達式x - x和0 0不相等”
(where here NaN denotes a quiet NaN as per F.2.1p1 "This specification does not define the behavior of signaling NaNs. It generally uses the term NaN to denote quiet NaNs")
(其中NaN表示根據F.2.1p1的安靜NaN“此規範沒有定義信号NaN的行為。它通常使用術語NaN來表示安靜的NaN”)#4樓
Since I see an answer impugning the standards compliance of Intel's compiler, and no one else has mentioned this, I will point out that both GCC and Clang have a mode in which they do something quite similar.
由于我看到一個答案違反了英特爾編譯器的标準符合性,并且沒有其他人提到這一點,我将指出GCC和Clang都有一種模式,他們做了類似的事情。Their default behavior is IEEE-compliant —
它們的預設行為符合IEEE标準 -$ g++ -O2 test.cc && ./a.out
neg: -nan
sub: nan nan nan
add: nan nan
div: nan nan nan
mul: nan nan
$ clang++ -O2 test.cc && ./a.out
neg: -nan
sub: -nan nan nan
add: nan nan
div: nan nan nan
mul: nan nan
— but if you ask for speed at the expense of correctness, you get what you ask for —
- 但如果你以犧牲正确性為代價來要求速度,那麼你得到你所要求的 -$ g++ -O2 -ffast-math test.cc && ./a.out
neg: -nan
sub: nan nan 0.000000
add: nan nan
div: nan nan 1.000000
mul: nan nan
$ clang++ -O2 -ffast-math test.cc && ./a.out
neg: -nan
sub: -nan nan 0.000000
add: nan nan
div: nan nan nan
mul: nan nan
I think it is entirely fair to criticize ICC's choice of default , but I would not read the entire Unix wars back into that decision.
我認為批評ICC的預設選擇是完全公平的,但我不會将整個Unix戰争重新納入該決定。