浮點(diǎn)數(shù)表示法的確存在精度丟失的問題,是由于最低有效位的限制造成的。而且一般其實(shí)際表示的數(shù)值會(huì)比規(guī)定的要小。比如2.6的浮點(diǎn)數(shù)表示為40266666H,而該數(shù)實(shí)際的值是2.5999999,這樣計(jì)算的結(jié)果是0.0999999比0.1小,不能輸出0.1,產(chǎn)生精度丟失,而如果將其表示更改為40266667H,其表示的實(shí)際值是2.6000001,而這個(gè)數(shù)可以輸出0.1的結(jié)果的。所以如果要使計(jì)算能夠得出正確結(jié)果,可以嘗試在輸入的時(shí)候?qū)⒂行粩?shù)擴(kuò)展,以確保得出正確結(jié)果。
創(chuàng)新互聯(lián)-云計(jì)算及IDC服務(wù)提供商,涵蓋公有云、IDC機(jī)房租用、成都電信服務(wù)器托管、等保安全、私有云建設(shè)等企業(yè)級(jí)互聯(lián)網(wǎng)基礎(chǔ)服務(wù),聯(lián)系電話:18980820575
比如要輸出2.6的結(jié)果,可以設(shè)sx=2.6000001,這樣可以使浮點(diǎn)數(shù)表示結(jié)果為大于2.6的盡可能小的值。如果要輸出2.1的結(jié)果,可以設(shè)sx=2.1000001。
int k=0;
float sx=2.6000001;
在進(jìn)行數(shù)據(jù)計(jì)算時(shí),小數(shù)也就是浮點(diǎn)數(shù)擁有不低的出場率。在常人看來,機(jī)器也就是計(jì)算機(jī)的數(shù)據(jù)運(yùn)算是不會(huì)出錯(cuò)的,沒錯(cuò),計(jì)算機(jī)進(jìn)行數(shù)據(jù)運(yùn)算的確不會(huì)犯錯(cuò),但小數(shù)運(yùn)算的誤差是免不了的。
來試一試。
在JS中寫上console.log(0.3-0.1);輸出到控制臺(tái)
是不是出乎意料,簡單的0.3-0.1=0.2這樣一道小學(xué)算術(shù)都沒算對(duì)。
在對(duì)于浮點(diǎn)數(shù)的四則運(yùn)算,幾乎所有的編程語言都會(huì)有類似精度誤差的問題。
只不過在 C++/C#/Java 這些語言中已經(jīng)封裝好了方法來避免精度的問題,而 JavaScript 是一門弱類型的語言,從設(shè)計(jì)思想上就沒有對(duì)浮點(diǎn)數(shù)有個(gè)嚴(yán)格的數(shù)據(jù)類型,所以精度誤差的問題就顯得格外突出,無法避免。
那么為什么會(huì)有這個(gè)誤差呢,誤差有沒有辦法解決呢。
首先看計(jì)算機(jī)是怎么進(jìn)行運(yùn)算的。大家都知道計(jì)算機(jī)是二進(jìn)制運(yùn)算。那么要計(jì)算0.3減0.1,就要先進(jìn)行換算。
console.log("0.3="+(0.3).toString(2));
console.log("0.1="+(0.1).toString(2));
console.log("0.3-0.1="+(0.3 - 0.1).toString(2));
輸出結(jié)果如下圖:
0.3與0.1轉(zhuǎn)換為二進(jìn)制的浮點(diǎn)數(shù)都是無限循環(huán)小數(shù)。但由于浮點(diǎn)數(shù)精度有限被強(qiáng)行截?cái)啵赞D(zhuǎn)回十進(jìn)制輸出的數(shù)據(jù)會(huì)有誤差。
那么如何解決這個(gè)問題。
最簡單的解決方案就是給出明確的精度要求,在返回值的過程中,計(jì)算機(jī)會(huì)自動(dòng)四舍五入。
console.log((0.3-0.1).toFixed(2));//輸出的結(jié)果是0.20;
然而這樣子解決有點(diǎn)勉強(qiáng)。
再看下面的方法
var s = Math.pow(10,8);
console.log((0.3 * s - 0.1 * s)/s);
輸出后結(jié)果為0.2,沒有誤差。為什么,上面是什么意思。
原來為了避免產(chǎn)生精度差異,我們要把需要計(jì)算的數(shù)字乘以 10 的 n 次冪,換算成計(jì)算機(jī)能夠精確識(shí)別的整數(shù),然后再除以 10 的 n 次冪,就能夠得到準(zhǔn)確的結(jié)果了。
大部分編程語言都是這樣處理精度差異的,這里就借用過來處理一下 JS 中的浮點(diǎn)數(shù)精度誤差。
在Excel進(jìn)行計(jì)算時(shí)在計(jì)算機(jī)中是轉(zhuǎn)換成二進(jìn)制進(jìn)算然后保留數(shù)值的,所以會(huì)出現(xiàn)誤差。解決方法:
1、打開excel表格,在單元格A1中輸入數(shù)字“2.88”,在單元格B1中輸入數(shù)字“5.89”。
2、在C1單元格中輸入計(jì)算公式:=(ROUND(A1,2))+ROUND(B1,2),意思為使用ROUND函數(shù)確保小數(shù)位為2位。
3、點(diǎn)擊回車生成函數(shù)公式計(jì)算結(jié)果,得到的數(shù)值為“8.77”。
4、復(fù)制C1單元格,在C2點(diǎn)擊右鍵,選擇“粘貼數(shù)值”。
5、粘貼之后,可以看到計(jì)算得到的數(shù)值是小數(shù)點(diǎn)顯示后兩位,沒有出現(xiàn)誤差。
首先,看一下浮點(diǎn)數(shù)誤差原因
浮點(diǎn)數(shù)的誤差的產(chǎn)生一般由于兩個(gè)原因
1)由于計(jì)算機(jī)內(nèi)部以二進(jìn)制保存,所以十進(jìn)制的有限位的小數(shù),在計(jì)算機(jī)內(nèi)部會(huì)是一個(gè)無限位的小數(shù)。
例如 十進(jìn)制的0.9雖然只有一位小數(shù),轉(zhuǎn)成2進(jìn)制是無限循環(huán)小數(shù)0.1110011001100110011...
2)計(jì)算機(jī)保存浮點(diǎn)數(shù)的精度有限,例如float可以保留十進(jìn)制最多7位(二進(jìn)制23位)有效數(shù)字,double 可以保留十進(jìn)制15~16位(二進(jìn)制52位)有效數(shù)字。那有效數(shù)字以后的就被忽略了。
例如上面的0.9的表示受精度所限,精度以后的就被忽略了,這樣
float時(shí),它是0.89999998
double時(shí),它是0.90000000000000002
每一次對(duì)浮點(diǎn)數(shù)的運(yùn)算都會(huì)導(dǎo)致小誤差,所以比較的時(shí)候不能用等于號(hào) 要這樣寫
i - 10.0 = 0.0000000001 這樣就會(huì)減少點(diǎn)誤差,而且你的第二個(gè)程序也會(huì)報(bào)yes了
浮點(diǎn)數(shù)的比較很麻煩,像while(sx=0.1)這個(gè)等號(hào)很不保險(xiǎn)
要判斷一個(gè)浮點(diǎn)數(shù)是否等于另外一個(gè)浮點(diǎn)數(shù),一般是求二者的差,差的絕對(duì)值小于某給定值就算相等 像這樣:
while((sx-0.1)0.00001(0.1-sx)0.00001)
{
sx=0;
printf("0.1=1\n");
}
總之,在程序中應(yīng)該盡量避免浮點(diǎn)數(shù)的比較
Golang Float乘Float高精度,轉(zhuǎn)Int高精度。
使用big.Float
bigF1 := new(big.Float).SetFloat64(f1)
bigF2 := new(big.Float).SetFloat64(f2)
mul := new(big.Float).Mul(bigF1, bigF2)
轉(zhuǎn)Int,先用上面的方法轉(zhuǎn)為big.Float,再用.String轉(zhuǎn)為字符串。
new(big.Int).SetString(bigFloat, 10) // 即可轉(zhuǎn)為big.Int
// big.Int可轉(zhuǎn)為常用的int類型。
// big.Float可轉(zhuǎn)為常用的Float類型。
// big.Float不能直接轉(zhuǎn)為Int類型。
func Sub(x float64, y float64, more ...float64) float64 {
floatX := new(big.Float).SetFloat64(x)
floatY := new(big.Float).SetFloat64(y)
result := new(big.Float).Sub(floatX, floatY)
if len(more) 0 {
? for _, m := range more {
? ? floatM := new(big.Float).SetFloat64(m)
? ? result = new(big.Float).Sub(result, floatM)
}
}
f, _ := strconv.ParseFloat(result.String(), 64)
return f
}
當(dāng)前文章:浮點(diǎn)誤差如何解決go語言,浮點(diǎn)數(shù)運(yùn)算誤差
當(dāng)前地址:http://chinadenli.net/article28/hescjp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、虛擬主機(jī)、建站公司、定制網(wǎng)站、網(wǎng)站導(dǎo)航、網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)