[英]Comparing floating-point 0
如果foo是float類型,則以下表達式是有效/推薦的嗎?
(0.0f == foo * float(0))
無論foo的值如何,它都具有預期的(數學)值嗎?
C ++標准是定義行為還是特定於實現?
好吧,首先它不是C ++標准的問題。 相反,問題在於您的浮點模型標准(最可能是IEEE)。
對於IEEE浮點數,這可能是安全的,因為float(0)
應該導致與0.0f相同的數字,並且乘以任何其他數字也應該是0.0f。
不安全的是做其他浮點運算(例如:用非整數加法和減法)並用0.0f檢查它們。
AFAIK,它不一定,也可能最終非常接近0。
通常最好與epsilon進行比較。 我使用這樣的函數進行這樣的比較:
float EpsilonEqual( float a, float b, float epsilon )
{
return fabsf( a - b ) < epsilon;
}
正如其他人已經提到的那樣,NaNs和Infinites可以搞砸這種比較。
但是,還有一個陷阱:在C ++中,你不能依賴float類型的編譯時表達式,比較等於在運行時計算的相同表達式。
原因是C ++允許以任何方式無限制地擴展fp計算的精度。 例:
#include <iostream>
// This provides sufficent obfuscation so that g++ doesn't just inline results.
bool obfuscatedTrue() { return true; }
int main()
{
using namespace std;
double const a = (obfuscatedTrue()? 3.0 : 0.3);
double const b = (obfuscatedTrue()? 7.0 : 0.7);
double const c = a/b;
cout << (c == a/b? "OK." : "\"Wrong\" comparision result.") << endl;
}
一個特定編譯器的結果:
C:\test> g++ --version | find "++"
g++ (TDM-2 mingw32) 4.4.1
C:\test> g++ fp_comparision_problem.cpp & a
"Wrong" comparision result.
C:\test> g++ -O fp_comparision_problem.cpp & a
OK.
C:\test> _
干杯&hth。,
- 阿爾夫
使用該特定語句,您可以非常確定結果將為0
並且比較結果為true
- 我認為C ++標准實際上沒有規定它,但任何合理的浮點類型實現都會有0
工作。
但是,對於大多數其他計算,結果不能完全等於數學上正確的結果:
為什么我的數字,如0.1 + 0.2加起來不是很好的一輪0.3,而是我得到一個奇怪的結果,如0.30000000000000004?
因為在內部,計算機使用的格式(二進制浮點)無法准確地表示0.1,0.2或0.3之類的數字。
編譯或解釋代碼時,“0.1”已經四舍五入到該格式中最接近的數字,即使在計算發生之前也會導致小的舍入誤差。
我剛剛在msdn中閱讀了有關VisualStudio 鏈接文本中 / fp選項的這篇文章
不允許對特殊值(NaN,+ infinity,-infinity,+ 0,-0)無效的表達式優化。 優化xx => 0,x * 0 => 0,x-0 => x,x + 0 => x,0-x => -x由於各種原因都無效(參見IEEE 754和C99標准) )。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.