官术网_书友最值得收藏!

1.4.2 浮點(diǎn)數(shù)運(yùn)算

在實(shí)際應(yīng)用中,特別是涉及金額計(jì)算時(shí),我們需要對(duì)浮點(diǎn)數(shù)執(zhí)行精確的計(jì)算操作,不希望有任何小誤差的出現(xiàn)。

浮點(diǎn)數(shù)的一個(gè)問題是它不能精確地表示十進(jìn)制數(shù),即使是最簡(jiǎn)單的數(shù)學(xué)運(yùn)算也會(huì)產(chǎn)生小的誤差,相關(guān)代碼(accurate_float.py)示例如下:


a = 2.1
b = 4.2
print(a + b)

這些誤差是由底層CPU和IEEE 754標(biāo)準(zhǔn)通過自己的浮點(diǎn)運(yùn)算單位去執(zhí)行算術(shù)運(yùn)算時(shí)產(chǎn)生的。由于Python的浮點(diǎn)數(shù)據(jù)類型使用底層表示存儲(chǔ)數(shù)據(jù),因此無法避免這樣的誤差。

如果想使浮點(diǎn)數(shù)運(yùn)算更加精確(并能容忍一定的性能損耗),可以使用decimal模塊,相關(guān)代碼(accurate_float.py)示例如下:


from decimal import Decimal
a = Decimal('2.1')
b = Decimal('4.2')
print(f'a + b = {a + b}')

初看起來,上面的代碼好像有點(diǎn)奇怪,比如用字符串來表示數(shù)字。然而,Decimal對(duì)象會(huì)像普通浮點(diǎn)數(shù)一樣工作(支持所有的常用數(shù)學(xué)運(yùn)算)。如果打印Decimal對(duì)象或者在字符串格式化函數(shù)中使用Decimal對(duì)象,其看起來和普通數(shù)字一樣。

decimal模塊的一個(gè)主要特征是允許控制計(jì)算的數(shù)字位數(shù)和四舍五入運(yùn)算。decimal模塊首先創(chuàng)建一個(gè)本地上下文并更改它的設(shè)置,相關(guān)代碼(accurate_float.py)示例如下:


from decimal import localcontext
a = Decimal('1.3')
b = Decimal('1.7')
print(f'a / b = {a / b}')
with localcontext() as ctx:
    ctx.prec = 3
    print(f'a / b = {a / b}')

with localcontext() as ctx:
    ctx.prec = 50
    print(f'a / b = { a / b}')

decimal模塊實(shí)現(xiàn)了IBM的通用小數(shù)運(yùn)算規(guī)范。Python新手會(huì)傾向于使用decimal模塊來處理浮點(diǎn)數(shù)的精確運(yùn)算,不過先理解應(yīng)用程序的目的是非常重要的。

如果你是在做科學(xué)計(jì)算、工程領(lǐng)域的計(jì)算或電腦繪圖,那么使用普通的浮點(diǎn)類型是比較普遍的做法。其中一個(gè)原因是,在真實(shí)世界中很少要求提供17位精度的計(jì)算結(jié)果。另一個(gè)原因是,原生的浮點(diǎn)數(shù)計(jì)算要快得多,在執(zhí)行大量運(yùn)算的時(shí)候速度也是非常重要的。

當(dāng)然,我們也不能完全忽略誤差,也得注意減法、大數(shù)和小數(shù)加法運(yùn)算所帶來的影響,相關(guān)代碼示例如下:


num_list = [1.23e+18, 1, -1.23e+18]
print(f'sum result is: {sum(num_list)}')

上述誤差可以利用math.fsum()方法來解決,示例如下:


import math
print(f'math sum result: {math.fsum(num_list)}')

對(duì)于其他的算法,我們應(yīng)該仔細(xì)研究它并理解它的誤差產(chǎn)生來源。

總的來說,decimal模塊主要用在涉及金融的領(lǐng)域。在金融領(lǐng)域,哪怕出現(xiàn)小小的誤差也是不允許的。Python和數(shù)據(jù)庫打交道的時(shí)候通常也會(huì)遇到Decimal對(duì)象,大多是在處理金融數(shù)據(jù)的時(shí)候。

主站蜘蛛池模板: 江都市| 阿拉善右旗| 安宁市| 阜康市| 朝阳县| 开远市| 松原市| 扎兰屯市| 界首市| 象山县| 旬邑县| 桦南县| 鹿邑县| 和政县| 绥江县| 石河子市| 镇平县| 宝清县| 远安县| 客服| 和顺县| 革吉县| 邢台市| 诸暨市| 浦东新区| 松溪县| 洪江市| 威海市| 曲沃县| 错那县| 滦南县| 乡宁县| 苍南县| 天峨县| 凤阳县| 阿拉善右旗| 蒲江县| 三台县| 塘沽区| 彰化市| 枣强县|