3 回答

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

TA貢獻(xiàn)1783條經(jīng)驗(yàn) 獲得超4個(gè)贊
嘗試運(yùn)行此代碼,結(jié)果將使原因顯而易見。
#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能夠準(zhǔn)確地表示1.1。當(dāng)您嘗試進(jìn)行比較時(shí),浮點(diǎn)數(shù)將隱式上轉(zhuǎn)換為雙精度。double數(shù)據(jù)類型可以準(zhǔn)確表示浮點(diǎn)數(shù)的內(nèi)容,因此比較得出false。

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