3 回答

TA貢獻1810條經驗 獲得超4個贊
使用float或double數字考慮的重要因素是:
精度和舍入
精度:
浮點數的精度是它可以表示多少個數字而不會丟失其包含的任何信息。
考慮分數1/3。該數字的十進制表示形式是0.33333333333333…3到無窮大。無限長數將需要無限存儲與精確的精度來示出,但float還是double數據類型通常僅具有4或8字節。因此,浮點數和雙數只能存儲一定數量的數字,其余數字勢必會丟失。因此,沒有確定精確的方法來表示浮點數或雙精度數,其數字需要比變量可容納的精度更高的精度。
舍入:和數字
之間沒有明顯差異。 考慮分數。在中,可以輕松地將表示為,并且可以將其視為易于表示的數字。但是,以二進制表示,由無限序列表示:binarydecimal (base 10)
1/10decimal0.10.10.10.00011001100110011…
一個例子:
#include <iomanip>
int main()
{
using namespace std;
cout << setprecision(17);
double dValue = 0.1;
cout << dValue << endl;
}
輸出為:
0.10000000000000001
并不是
0.1.
這是因為雙精度數由于其有限的內存而不得不截斷近似值,從而導致數字不完全相等0.1。這種情況稱為舍入誤差。
每當比較兩個接近的浮點數和雙數時,這樣的舍入錯誤就會出現,最終比較會產生錯誤的結果,這是您絕不應該比較浮點數或重復使用的原因==。
您能做的最好的就是找出它們的差,并檢查其是否小于ε。
abs(x - y) < epsilon

TA貢獻1783條經驗 獲得超4個贊
嘗試運行此代碼,結果將使原因顯而易見。
#include <iomanip>
#include <iostream>
int main()
{
std::cout << std::setprecision(100) << (double)1.1 << std::endl;
std::cout << std::setprecision(100) << (float)1.1 << std::endl;
std::cout << std::setprecision(100) << (double)((float)1.1) << std::endl;
}
輸出:
1.100000000000000088817841970012523233890533447265625
1.10000002384185791015625
1.10000002384185791015625
既不float也不double能夠準確地表示1.1。當您嘗試進行比較時,浮點數將隱式上轉換為雙精度。double數據類型可以準確表示浮點數的內容,因此比較得出false。

TA貢獻1951條經驗 獲得超3個贊
通常,您不應該使用來比較浮點數與浮點數,雙精度數與雙精度數或浮點數與雙精度數==。
最佳做法是將它們相減,并檢查差的絕對值是否小于較小的ε。
if(std::fabs(f - d) < std::numeric_limits<float>::epsilon())
{
// ...
}
原因之一是因為浮點數(或多或少)是二進制分數,并且只能近似許多小數。必須將許多十進制數轉換為重復的二進制“十進制”或無理數。這將引入舍入誤差。
來自維基百科:
例如,不能使用二進制基數將1/5精確地表示為浮點數,而可以使用十進制基數精確地表示1/5。
在您的特定情況下,浮點數和雙精度數對于必須用于以1.1二進制表示的非理性/重復分數的舍入將有所不同。在它們對應的轉換引入了不同級別的舍入誤差之后,將很難使它們“相等”。
我上面給出的代碼通過簡單地檢查值是否在很短的增量內來解決此問題。您的比較從“這些值相等嗎?”更改為 “這些值是否彼此之間的誤差很???”
另外,請參見以下問題:進行浮點和雙重比較的最有效方法是什么?
浮點數還有很多其他奇怪的地方,打破了簡單的相等比較。查看本文以了解其中的一些描述:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
- 3 回答
- 0 關注
- 616 瀏覽
添加回答
舉報