溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決

發(fā)布時(shí)間:2020-11-02 16:10:55 來(lái)源:億速云 閱讀:200 作者:Leah 欄目:開發(fā)技術(shù)

Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決?相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

一、問(wèn)題說(shuō)明

以前對(duì)浮點(diǎn)數(shù)運(yùn)行沒(méi)有沒(méi)有太在意。昨天同事要求把百分比結(jié)果保存到文件上,然后就以保存1位小數(shù)的形式給他保存了。

但是今天同事運(yùn)行時(shí)問(wèn)能不能統(tǒng)一以一位小數(shù)的形式保存,當(dāng)時(shí)覺(jué)得很奇怪昨天就是以一位小數(shù)形式存的怎么還會(huì)提這種要求呢。

其給回的截圖確實(shí)是部分是一位小數(shù)的,但一部分是很長(zhǎng)的。查看代碼都統(tǒng)一如下格式:

# 使用round保留三位小數(shù),然后乘以100,最后格式化為帶百分號(hào)的字符串
rate=f"{round(x/y,3) * 100}%"

代碼上沒(méi)看出什么問(wèn)題,直接運(yùn)行確實(shí)是有些結(jié)果是一長(zhǎng)串的。進(jìn)行調(diào)試發(fā)現(xiàn)當(dāng)x為37y為76時(shí)即會(huì)出現(xiàn)問(wèn)題,如下圖所示:

Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決

進(jìn)行步驟拆分,發(fā)現(xiàn)round方法沒(méi)有問(wèn)題,問(wèn)題在浮點(diǎn)數(shù)乘以100上(同時(shí)如下圖可以看到也不是所有浮點(diǎn)數(shù)乘都有問(wèn)題)

Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決

二、原因探究

搞不清原因,直到看到這篇文章:https://www.programiz.com/python-programming/numbers

大意是說(shuō)二進(jìn)制對(duì)很多浮點(diǎn)數(shù)無(wú)法準(zhǔn)確表示只能用一個(gè)近似值代替,而當(dāng)使用這些以近似值代替的浮點(diǎn)數(shù)進(jìn)行進(jìn)算時(shí)本質(zhì)上是這些進(jìn)似值參與了運(yùn)算,出來(lái)的結(jié)果也就是進(jìn)似值運(yùn)算后的結(jié)果。

也就是說(shuō),一是這不是乘100的問(wèn)題也不是乘法的問(wèn)題而是整個(gè)浮點(diǎn)數(shù)運(yùn)算都有問(wèn)題,二是這不是python的問(wèn)題是計(jì)算機(jī)浮點(diǎn)數(shù)存儲(chǔ)的問(wèn)題像C、Java等其他計(jì)算機(jī)語(yǔ)言進(jìn)行運(yùn)算都會(huì)有問(wèn)題。

Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決

可能有人會(huì)疑惑:為什么二進(jìn)制可以表示2不能表示0.2呢?

這是因?yàn)閿?shù)值和字符串是不一樣的,如果是字符串那么表示2.2點(diǎn)的左右兩邊的2編碼是一樣的就可以了(如ASCII碼:504650),但數(shù)值不是這樣,數(shù)值的整數(shù)部分和小數(shù)部分需要一個(gè)統(tǒng)一的表示形式,那就是加權(quán)位計(jì)數(shù)法。

整數(shù)部分都要以2的0次方(20)到2的無(wú)窮次方(2∞)表示,這沒(méi)有問(wèn)題,只要長(zhǎng)度足夠就能表示出所有奇數(shù)和偶數(shù)。2 = 1 * 21 + 0 * 20 = 10

小數(shù)部分都要以2的-1次方(2-1)到2的負(fù)無(wú)窮次方(2-∞)表示,這就有問(wèn)題,因?yàn)楸热?-1...2-∞不管怎么組合都不能完全等于0.2。0.2 = 0 * 2-1 + 0 * 2-2 + 1 * 2-3 ...

三、處理辦法

這情況讓我想起上份工作局方領(lǐng)導(dǎo)的一句話,應(yīng)該是“可以理解但不能接受”。

原理上二進(jìn)制無(wú)法精確表示一些浮點(diǎn)數(shù)可以理解,但是就這么返回個(gè)顯然錯(cuò)誤的結(jié)果給用戶那是無(wú)法接受的。

python提供了Decimal()方法讓浮點(diǎn)運(yùn)算結(jié)果可以和人平時(shí)運(yùn)算的結(jié)果一樣。(Decimal本質(zhì)應(yīng)該還是通過(guò)加長(zhǎng)長(zhǎng)度提高精度)

Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決

# Decimal傳字符串才能準(zhǔn)確表示,所以需要先用str()把round()的結(jié)果轉(zhuǎn)為字符串
rate=f"{Decimal(str(round(x/y,3))) * 100}%"

# 其實(shí)上邊的結(jié)果出來(lái)是48.700%的形式,即三位小數(shù)的形式并不太符合我們保留一位小數(shù)的想法,真正符合想法得下面這樣
# rate=f"{round(Decimal(str(round(x/y,3))) * 100, 1)}%"

# 其實(shí)我們說(shuō)了這么多,我們都是建立在決定保留多少位再乘100這個(gè)前提下,倘若我們先乘100后決定保留幾位那都不需要用Decimal
# rate=f"{round(x/y*100,1)}%"

Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決

看完上述內(nèi)容,你們掌握Python浮點(diǎn)型運(yùn)算結(jié)果不正確怎么解決的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI