日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

【Python】浮点数计算时的不准确性以及如何进行精确计算

發(fā)布時(shí)間:2025/3/15 python 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Python】浮点数计算时的不准确性以及如何进行精确计算 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

浮點(diǎn)數(shù)一個(gè)普遍的問題就是在計(jì)算機(jī)的世界中,浮點(diǎn)數(shù)并不能準(zhǔn)確地表示十進(jìn)制。并且,即便是最簡單的數(shù)學(xué)運(yùn)算,也會帶來不可控制的后果。因?yàn)?#xff0c;在計(jì)算機(jī)的世界中只認(rèn)識0與1
因?yàn)樵谟?jì)算機(jī)里面,小數(shù)是不精確的,例如1.115在計(jì)算機(jī)中實(shí)際上是1.1149999999999999911182,所以當(dāng)你對這個(gè)小數(shù)精確到小數(shù)點(diǎn)后兩位的時(shí)候,實(shí)際上小數(shù)點(diǎn)后第三位是4,所以四舍五入,因此結(jié)果為1.11。
這種說法,對了一半。因?yàn)椴⒉皇撬械男?shù)在計(jì)算機(jī)中都是不精確的。例如0.125這個(gè)小數(shù)在計(jì)算機(jī)中就是精確的,它就是0.125,沒有省略后面的值,沒有近似,它確確實(shí)實(shí)就是0.125。
但是如果我們在Python中把0.125精確到小數(shù)點(diǎn)后兩位,那么它的就會變成0.12,為什么在這里四舍了?
還有更奇怪的,另一個(gè)在計(jì)算機(jī)里面能夠精確表示的小數(shù)0.375,我們來看看精確到小數(shù)點(diǎn)后兩位是多少:,為什么這里又五入了?因?yàn)樵赑ython 3里面,round對小數(shù)的精確度采用了四舍六入五成雙的方式。
如果你寫過大學(xué)物理的實(shí)驗(yàn)報(bào)告,那么你應(yīng)該會記得老師講過,直接使用四舍五入,最后的結(jié)果可能會偏高。所以需要使用奇進(jìn)偶舍的處理方法。
例如對于一個(gè)小數(shù)a.bcd,需要精確到小數(shù)點(diǎn)后兩位,那么就要看小數(shù)點(diǎn)后第三位: ??如果d小于5,直接舍去;如果d大于5,直接進(jìn)位;
如果d等于5:d后面沒有數(shù)據(jù),且c為偶數(shù),那么不進(jìn)位,保留c。d后面沒有數(shù)據(jù),且c為奇數(shù),那么進(jìn)位,c變成(c + 1)
python中的decimal模塊可以解決上面的煩惱?
decimal模塊中,可以通過整數(shù),字符串或原則構(gòu)建decimal.Decimal對象。如果是浮點(diǎn)數(shù),特別注意因?yàn)楦↑c(diǎn)數(shù)本身存在誤差,需要先將浮點(diǎn)數(shù)轉(zhuǎn)化為字符串。
當(dāng)然精度提升的同時(shí),肯定帶來的是性能的損失。在對數(shù)據(jù)要求特別精確的場合(例如財(cái)務(wù)結(jié)算),這些性能的損失是值得的。
但是如果是大規(guī)模的科學(xué)計(jì)算,就需要考慮運(yùn)行效率了。畢竟原生的float比Decimal對象肯定是要快很多的。

Python提供了decimal模塊用于十進(jìn)制數(shù)學(xué)計(jì)算,它具有以下特點(diǎn):
1.提供十進(jìn)制數(shù)據(jù)類型,并且存儲為十進(jìn)制數(shù)序列;
2.有界精度:用于存儲數(shù)字的位數(shù)是固定的,可以通過decimal.getcontext().prec=x 來設(shè)定,不同的數(shù)字可以有不同的精度
3.浮點(diǎn):十進(jìn)制小數(shù)點(diǎn)的位置不固定(但位數(shù)是固定的)

python decimal.quantize()參數(shù)rounding的decimal文檔里面的解釋:
ROUND_CEILING (towards Infinity),
ROUND_DOWN (towards zero),
ROUND_FLOOR (towards -Infinity),
ROUND_HALF_DOWN (to nearest with ties going towards zero),
ROUND_HALF_EVEN (to nearest with ties going to nearest even integer),
ROUND_HALF_UP (to nearest with ties going away from zero), or
ROUND_UP (away from zero).
ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero)

下面通過具體代碼理解每個(gè)參數(shù)

# -*- coding: utf-8 -*- ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' #作者:cacho_37967865 #博客:https://blog.csdn.net/sinat_37967865 #文件:dealFloat.py #日期:2019-08-01 #備注:python使用浮點(diǎn)類型float計(jì)算后,數(shù)值可能不對,這時(shí)候需要使用decimal模塊 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''from decimal import Decimal,getcontext from decimal import ROUND_UP,ROUND_DOWN,ROUND_HALF_UP,ROUND_HALF_DOWN,ROUND_HALF_EVEN,ROUND_05UP,ROUND_CEILING ,ROUND_FLOORx = 4.20 y = 2.10 a = 1.20 b = 2.30 d = 195.00def float_info():# a.bcd ,精確2位小數(shù)點(diǎn)i = 1.115 # 在計(jì)算機(jī)中實(shí)際上是1.1149999999999999911182 四舍五入:1.11j = 0.125 # d后面沒有數(shù)據(jù),且c為偶數(shù),那么不進(jìn)位,保留c 四舍五入:0.12l = 0.1251 # d后面有數(shù)據(jù),c變成(c + 1) 四舍五入:0.13k = 0.375 # d后面沒有數(shù)據(jù),且c為奇數(shù),那么進(jìn)位,c變成(c + 1) 四舍五入:0.38print('四舍五入:',round(i,2))print('四舍五入:',round(j, 2))print('四舍五入:',round(l, 2))print('四舍五入:',round(k, 2))def decimal_info():# a.bcd ,精確2位小數(shù)點(diǎn) 默認(rèn)進(jìn)位方式i = 1.115 # 在計(jì)算機(jī)中實(shí)際上是1.1149999999999999911182 四舍五入:1.11j = 0.125 # d后面沒有數(shù)據(jù),且c為偶數(shù),那么不進(jìn)位,保留c 四舍五入:0.12l = 0.1251 # d后面有數(shù)據(jù),c變成(c + 1) 四舍五入:0.13k = 0.375 # d后面沒有數(shù)據(jù),且c為奇數(shù),那么進(jìn)位,c變成(c + 1) 四舍五入:0.38print('浮點(diǎn)型數(shù)據(jù)不精確:',Decimal(i))print('浮點(diǎn)型數(shù)據(jù)也可能精確:', Decimal(j))print('傳入的是字符串默認(rèn)方式四舍五入:', Decimal(str(i)).quantize(Decimal('0.00'))) # 1.12print('傳入的是浮點(diǎn)型默認(rèn)方式四舍五入:',Decimal(i).quantize(Decimal('0.00'))) # 1.11print('傳入的是浮點(diǎn)型默認(rèn)方式四舍五入:',Decimal(j).quantize(Decimal('0.00')))print('傳入的是浮點(diǎn)型默認(rèn)方式四舍五入:',Decimal(l).quantize(Decimal('0.00')))print('傳入的是浮點(diǎn)型默認(rèn)方式四舍五入:',Decimal(k).quantize(Decimal('0.00')))# 最好傳入字符串print('傳入的是字符串真實(shí)四舍五入:', Decimal(str(i)).quantize(Decimal('0.00'), ROUND_HALF_UP))print('傳入的是字符串真實(shí)四舍五入:', Decimal(str(j)).quantize(Decimal('0.00'), ROUND_HALF_UP))print('傳入的是字符串真實(shí)四舍五入:', Decimal(str(l)).quantize(Decimal('0.00'), ROUND_HALF_UP))print('傳入的是字符串真實(shí)四舍五入:', Decimal(str(k)).quantize(Decimal('0.00'),ROUND_HALF_UP))print('傳入的是字符串向上取值:', Decimal('0.121').quantize(Decimal('0.00'), ROUND_UP)) # 向上入 0.13print('傳入的是字符串向下取值:', Decimal('0.129').quantize(Decimal('0.00'), ROUND_DOWN)) # 向下舍 0.12print('傳入的是字符串向上四舍五入:', Decimal('0.125').quantize(Decimal('0.00'), ROUND_HALF_UP)) # 最后一位5向上入 0.13print('傳入的是字符串向下四舍五入:', Decimal('0.125').quantize(Decimal('0.00'), ROUND_HALF_DOWN)) # 最后一位5向下舍 0.12print('傳入的是字符串默認(rèn)方式四舍五入:', Decimal('0.125').quantize(Decimal('0.00'), ROUND_HALF_EVEN)) # 默認(rèn)四舍五入方式 0.12 quansize的默認(rèn)設(shè)置值print('傳入的是字符串默認(rèn)方式四舍五入:', Decimal('0.375').quantize(Decimal('0.00'), ROUND_HALF_EVEN)) # 默認(rèn)四舍五入方式 0.38print('傳入的是字符串精確位數(shù)字為5入:', Decimal('5.351').quantize(Decimal('0.00'), ROUND_05UP)) # 精確的最后一位為0或者5向上入,否者向下舍5.36print('傳入的是字符串精確位數(shù)字為0入:', Decimal('5.301').quantize(Decimal('0.00'), ROUND_05UP)) # 精確的最后一位為0或者5向上入,否者向下舍5.31print('傳入的是字符串精確位數(shù)字非0和5舍:', Decimal('5.399').quantize(Decimal('0.00'), ROUND_05UP)) # 精確的最后一位為0或者5向上入,否者向下舍5.39print('傳入的是字符串正數(shù)時(shí)與ROUND_UP一致:', Decimal('5.391').quantize(Decimal('0.00'), ROUND_CEILING)) # 5.40print('傳入的是字符串正數(shù)時(shí)與ROUND_DOWN一致:', Decimal('5.399').quantize(Decimal('0.00'), ROUND_FLOOR)) # 5.39print('傳入的是字符串負(fù)數(shù)時(shí)與ROUND_DOWN一致:', Decimal('-5.399').quantize(Decimal('0.00'), ROUND_CEILING)) # -5.39 趨近于正無窮print('傳入的是字符串負(fù)數(shù)時(shí)與ROUND_UP一致:', Decimal('-5.399').quantize(Decimal('0.00'), ROUND_FLOOR)) # -5.40 趨近于負(fù)無窮print('傳入的是字符串與正負(fù)無關(guān),最后一位始終進(jìn):', Decimal('-5.399').quantize(Decimal('0.00'), ROUND_UP))def float_deal():z = x + y # 6.300000000000001print(z)if z == 6.30:print("z計(jì)算正確")else:print("z計(jì)算錯(cuò)誤")c = a + bprint(c)if c == 3.5:print("c計(jì)算正確")else:print("c計(jì)算錯(cuò)誤")e = round(195.00 / 24,2)print(e)if e == 8.13:print("e四舍五入正確")else:print("e四舍五入錯(cuò)誤")def decimal_deal():getcontext().prec = 3 # 設(shè)置精確值,只針對計(jì)算時(shí)無法除凈時(shí)z = Decimal(str(x)) + Decimal(str(y))print(type(z),z)e = Decimal('195.00') / Decimal('24')print(e)if __name__ == '__main__':float_info()decimal_info()#float_deal()#decimal_deal()

?

總結(jié)

以上是生活随笔為你收集整理的【Python】浮点数计算时的不准确性以及如何进行精确计算的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。