国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Python > 正文

Python浮點數四舍五入問題的分析與解決方法

2024-09-09 19:02:46
字體:
來源:轉載
供稿:網友

問題

昨天遇到一個問題,在 6.6045 保留三位小數時,使用 round() 函數進行計算,我們希望得到 6.605,然而:

>>> round(6.6045, 3)6.604

網上有人說,因為在計算機里面,小數是不精確的,例如 1.115 在計算機中實際上是 1.114999999999999991182,所以當你對這個小數精確到小數點后兩位的時候,實際上小數點后第三位是 4,所以四舍五入,結果為 1.11.

這種說法,對了一半。

因為并不是所有的小數在計算機中都是不精確的。例如 0.125 這個小數在計算機中就是精確的,它就是 0.125,沒有省略后面的值,沒有近似,它確確實實就是 0.125.

但是如果我們在 Python 中運行:

>>> round(0.125, 2)0.12

為什么在這里四舍了?

還有更奇怪的,另一個在計算機里面能夠精確表示的小數 0.375,我們來看看精確到小數點后兩位是多少:

>>> round(0.375, 2)0.38

為什么在這里又五入了?

解析

因為在 Python3 里面,round 對小數的精確度采用了四舍六入五成雙的方式。

如果你寫過大學物理的實驗報告,那么你應該會記得老師講過,直接使用四舍五入,最后的結果可能會偏高,所以需要使用奇進偶舍的處理方法。

例如對于一個浮點數 a.bcd,需要精確到小數點后兩位,那么就要看小數點后第三位:

如果 d 小于 5,直接舍去; 如果 d 大于 5,直接進位; 如果 d 等于 5:
d 后面沒有數據,且 c 為偶數,那么不進位,保留 c
d 后面沒有數據,且 c 為奇數,那么進位,c 變成 (c + 1) 如果 d 后面還有非 0 數字,例如實際上小數為 a.bcdef,此時一定要進位,c 變成 (c + 1)

關于奇進偶舍,有興趣的朋友可以在維基百科搜索這兩個詞條:數值修約和奇進偶舍。

所以,round 給出的結果如果跟設想的不一樣,那么需要考慮兩個原因:
你的這個小數在計算機中能不能被精確儲存?如果不能,那么它可能并沒有達到四舍五入的標準,例如 1.115,它的小數點后第三位實際上是 4,當然會被舍去。
如果你的這個小數在計算機中能被精確表示,那么,round 采用的進位機制是奇進偶舍,所以這取決于你要保留的那一位,它是奇數還是偶數,以及它的下一位后面還有沒有數據。

關于奇進偶舍,有興趣的朋友可以在搜索這兩個詞條:數值修約和奇進偶舍。

回到最開始的問題,對于 6.6045 這個浮點數,我們在 Scheme 中查看一下它的精確形式:

> (exact 6.6045)3718002967371055/562949953421312

也就是說它是不能被精確儲存的,大概表現為 6.60449999999999…的形式,因此四舍五入的時候得到了 6.604。

如何正確進行四舍五入

如果要實現數學上的四舍五入,那么就需要使用 decimal 模塊,具體用法參考官方文檔:https://docs.python.org/zh-cn...。
其中 quantize 的函數原型和文檔說明,提到了可以通過指定 rounding 參數來確定進位方式。如果沒有指定 rounding 參數,那么會默認使用上下文提供的進位方式。

現在我們來查看一下默認的上下文中的進位方式是什么:

>>> from decimal import getcontext>>> getcontext().rounding'ROUND_HALF_EVEN'

ROUND_HALF_EVEN 實際上就是奇進偶舍,如果要指定真正的四舍五入,那么我們需要在 quantize 中指定進位方式為 ROUND_HALF_UP:

>>> from decimal import Decimal, ROUND_HALF_UP>>> Decimal('0.125').quantize(Decimal('0.00'), rounding=ROUND_HALF_UP)Decimal('0.13')
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武平县| 剑川县| 满城县| 嘉峪关市| 聂拉木县| 夏河县| 新化县| 长治市| 荆门市| 堆龙德庆县| 兴业县| 莱阳市| 亳州市| 淅川县| 晋中市| 米林县| 紫金县| 华安县| 镇雄县| 青阳县| 施甸县| 依兰县| 吴忠市| 芮城县| 顺平县| 和平区| 麻阳| 崇文区| 连山| 类乌齐县| 西盟| 娄烦县| 鄯善县| 石门县| 镶黄旗| 黄陵县| 大渡口区| 桐乡市| 绩溪县| 茶陵县| 丰台区|