有沒有使用「==」判斷浮點數相等與否出現錯誤的例子?
有沒有使用「==」判斷浮點數相等與否出現錯誤的例子?
也就是,什麼情況下「==」會失效?
一般來講,==和!=在針對浮點數的時候,兩邊都必須是字面量。意思就是,左邊是1.0,右邊是1.0,他們中間複製了幾次,總之只要他們不是被計算出來的,可以比較。
但是如果是計算出來的——可沒有人告訴你0.1+0.1就是0.2。0.1這個值其實是不存在的,因為它不能被處理成一個2進位的有限小數。所以你對兩個不存在的值進行相加,就會得到一些奇怪的誤差,所以才不能==。
到底0.1+0.1和0.2相比,到底是誰大誰小還是一樣,完全取決於你的C++編譯器在對付2進位無限小數的時候,到底用什麼樣的截斷策略——譬如說ceil、floor、round,都是有可能的。如果這個策略你已經清楚了,那你自己也可以判斷到底是什麼結果。
反過來,只要是精度以內的二進位有限數字就可以。譬如說,0.25+0.25,肯定就==0.5,沒有問題。
15.1 * 100 + 0.9 * 100 == 16.0 * 100 返回值為true
16.1 * 100 + 0.9 * 100 == 17.0 * 100 返回值為false
(16.1 + 0.9) * 100 == 17.0 * 100 返回值為true
16.1 + 0.9 == 17.0 返回值為true
就問你怕了沒
這個問題之前在《高質量c++編程指南》中看到過,現引用原文:
【規則4-3-3】不可將浮點變數用「==」或「!=」與任何數字比較。
千萬要留意,無論是float 還是double 類型的變數,都有精度限制。所以一定要避
免將浮點變數用「==」或「!=」與數字比較,應該設法轉化成「&>=」或「&<=」形式。假設浮點變數的名字為x,應當將if (x == 0.0) // 隱含錯誤的比較轉化為if ((x&>=-EPSINON) (x&<=EPSINON))其中EPSINON 是允許的誤差(即精度)。應該可以回答你的問題以前看過一篇博文,解釋的比較清楚,原文找不到了,大意就是float佔4位元組,01排列組合最多4294967296種可能(40多億),但float的取值範圍是-2^128 ~ +2^128遠遠多於理論值,因此其中絕大多數都是不精確的
舉例來說,0.1~0.9這9個數中只有0.5能用二進位精確表示,其它全是不精確的近似值,因此積累一定量後肯定有較大誤差的,比如最後輸出what the fuck,調試可得f=0.9999999999999#include&
int main()
{
float f=0.0f;
for(int i=0;i&<10;++i)
{
f+=0.1;
}
if(f==1.0)
{
std::cout&<&<"all right"&<&
兩種數的獲取方式不一樣。比如一個是字面量另一個是計算量。這樣就可能不相等但是也有例外。比如符合c++中的is_iec559規範也能確保相等x == sqrt(x*x)
例子:
double a = 3456789.0,
b = 0.3456789;
while (a &> 1)
a/=10.0;
==是判斷二進位位,幾乎任何時候都會出現錯誤。
IEEE floating point 或 IEEE 854 浮點數的基數為10時,可以避免這個問題。PS: 代碼插入真是難用得一塌糊塗!有啊。記得是某次暑期多校賽還是網路賽還是隊內訓練賽來著。使用fabs(x-y)&<=1e-8,結果錯了了。後來改為x==y就過了。
簡單來說,當二進位不能精確表示的數進行運算時就可能會出現浮點誤差。
float a = 0.1;
float b = 0.2;
float c = 0.3; if (a + b == c) cout &<&< "==" &<&< endl; else cout &<&< "!=" &<&< endl;我這邊就舉一個關於浮點數進度的小栗子給大家看看。在我們經常設置機器參數的過程中,有時候需要設置機器的浮點數參數,比如說角度參數(有些編碼器的精度非常的高)。如果你在上位機中設置的邏輯是:如果讀取的機器參數不等於我設置的參數,那就就發送數據去修改機器的參數,直到二者相等。如果你是這樣的邏輯,那恭喜你,上位機和機器成功的掛了。因為數據在傳輸和捨棄的時候精度一般會損失,一般情況下二者是不會相等的。我想說的是什麼,我在工程中遇到的問題給我的結論是:沒有絕對的等於,只有誤差允許內的相等。在做上位機的時候也會依然考慮到這個情況,編譯器內部也是沒有絕對的等於。只是恰好在它誤差允許範圍內而已。所以浮點數用等於,你就可以考慮一下時候可以用大於,小於來替代,我覺得會更嚴謹。
數值分析果然是程序員必修課
樓主去做兩道計算幾何的題就知道了....
x y是否相等一般是判斷abs(x-y)&<=1e-8 這個1e-8是自己設立的任意精度....
浮點數沒有這樣判斷的~應該是相減小於一個很小的數
前面那麼多人解釋了,我來解釋下根本原因吧。大部分電腦的浮點數表示使用的是IEEE754浮點數標準。比如1.2500012是3fa0000a1.2500013也是1.2500014是3fa0000b1.2500015是3fa0000c你會發現1.2500012f等於1.2500013f,但是14和15不想等
這並不需要數值分析啊,祭祖就能告訴你不能亂==了吧
。。。這不是經常發生的嗎?典型情況是在大量計算而結果趨近於0的時候的,一個絕對值很小的數和0.0使用==得到的是false。所以在競賽的時候我們一般會根據題目要求的精讀設定一個閾值,例如const double eps =1e-7;bool isEqual(double a, double b){ return fabs(a - b) < eps;}
0.1 + 0.2==0.3js 內 false
#include&
#include&
int main(){
float x = 1.0f;
float y = 1.0f / 10;
printf("%.10f %.10f
",x,10.0*y);
if (10.0 * y == x){
printf("10.0*y == x
");
}
return 0;
}
先說結論,沒有。
舉個例子,你把int叫做「整數」,是不是說int就是你上數學課的整數了?當然不是,int就是int,是c代碼里的一個抽象的東西。「整數」可以超級大,int是有範圍的。只不過是當數據不大時int和整數在數學上的表現極為相近而已。
同理,float就是float,float不是浮點數。==也只能判斷float是不是相等,不能判斷浮點數是不是相等。無論==的內部實現和你的數學常識有多大差異,只要==認為float相等,他們就一定是相等,否則就一定不等。問題出在你平時用的浮點數相等實際是在大腦里作了一個強制轉換,把浮點數轉換成了float,這個強制轉換是不一定正確也不一定可逆的。
使用兩個數差絕對值小於一個小量來進行浮點數是否相等的判斷,這大概是唯一的方法。
推薦閱讀:
※怎樣開發一款有限元軟體,從哪些方面學習?
※C++ #include " " 與 <>有什麼區別?
※C++ 函數返回局部變數的std::move()問題?
※在開發大C++工程的時候如何判斷和避免循環include?
※為什麼C++使用sizeof關鍵字的時候不需要include <cstddef>頭文件就可以使用?