国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

為什么你需要少看垃圾博客以及如何在Python里精確地四舍五入

Object / 1931人閱讀

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

今天又有一個Python初學者被中文技術博客中的垃圾文章給誤導了。

這位初學者的問題是:

在Python中,如何精確地進行浮點數的四舍五入,保留兩位小數?

如果你在Google或者百度上搜索,你會發現大量的來自CSDN或者簡書上面的文章講到這一點,但是他們的說法無外乎下面幾種:

連例子都不舉的垃圾文章

如下圖所示,懶得吐槽。

使用round函數

他們舉的例子為:

>>> round(1.234, 2)
1.23

這種文章,他只演示了四舍,但是卻沒有演示五入。所以如果你代碼稍作修改,就會發現有問題:

>>> round(11.245, 2)
11.24
先放大再縮小

這種文章稍微好一點,知道多舉幾個例子:

然而這種文章也是漏洞百出,只要你多嘗試幾個數字就會發現問題,在Python 2和Python 3下面,效果是不一樣的。先來看看Python 2下面的運行效果:

在Python 2里面,直接使用round1.125精確到兩位小數后為1.13,而1.115精確到兩位小數后是1.11

再來看看Python 3下面的效果:

在Python 3下面,1.125在精確到兩位小數以后是1.12

他舉的例子,在Python 3中先放大再縮小,也并不總是正確。

裝逼貨

還有一種裝逼貨,文章和先放大再縮小差不多,但是他還知道decimal這個模塊。

不過他的使用方法,大家看他吧

具體原因不詳 ????

不推薦使用這個方法???

這種人要先裝個逼,表示自己知道有這樣一個庫,但是用起來發現有問題,而且不知道原因,所以不建議大家使用。

decimal是專門為高精度計算用的模塊,他竟然說不建議大家使用???

round到底出了什么問題?

罵完了,我們來說說,在Python 3里面,round這個內置的函數到底有什么問題。

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

這種說法,對了一半。

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

但是如果我們在Python中把0.125精確到小數點后兩位,那么它的就會變成0.12

>>> round(0.125, 2)
0.12

為什么在這里四舍了?

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

>>> round(0.375, 2)
0.38

為什么這里又五入了?

因為在Python 3里面,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采用的進位機制是奇進偶舍,所以這取決于你要保留的那一位,它是奇數還是偶數,以及它的下一位后面還有沒有數據。

如何正確進行四舍五入

如果要實現我們數學上的四舍五入,那么就需要使用decimal模塊。

如何正確使用decimal模塊呢?

看官方文檔,不要看中文垃圾博客!!!

看官方文檔,不要看中文垃圾博客!!!

看官方文檔,不要看中文垃圾博客!!!

不要擔心看不懂英文,Python已經推出了官方中文文檔(有些函數的使用方法還沒有翻譯完成)。

我們來看一下:https://docs.python.org/zh-cn...

官方文檔給出了具體的寫法:

>>>Decimal("1.41421356").quantize(Decimal("1.000"))
Decimal("1.414")

那么我們來測試一下,0.1250.375分別保留兩位小數是多少:

>>> from decimal import Decimal
>>> Decimal("0.125").quantize(Decimal("0.00"))
Decimal("0.12")
>>> Decimal("0.375").quantize(Decimal("0.00"))
Decimal("0.38")

怎么結果和round一樣?我們來看看文檔中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.375").quantize(Decimal("0.00"), rounding=ROUND_HALF_UP)
Decimal("0.38")
>>> Decimal("0.125").quantize(Decimal("0.00"), rounding=ROUND_HALF_UP)
Decimal("0.13")

現在看起來一切都正常了。

那么會不會有人進一步追問一下,如果Decimal接收的參數不是字符串,而是浮點數會怎么樣呢?

來實驗一下:

>>> Decimal(0.375).quantize(Decimal("0.00"), rounding=ROUND_HALF_UP)
Decimal("0.38")
>>> Decimal(0.125).quantize(Decimal("0.00"), rounding=ROUND_HALF_UP)
Decimal("0.13")

那是不是說明,在Decimal的第一個參數,可以直接傳浮點數呢?

我們換一個數來測試一下:

>>> Decimal(11.245).quantize(Decimal("0.00"), rounding=ROUND_HALF_UP)
Decimal("11.24")
>>> Decimal("11.245").quantize(Decimal("0.00"), rounding=ROUND_HALF_UP)
Decimal("11.25")

為什么浮點數11.245和字符串"11.245",傳進去以后,結果不一樣?

我們繼續在文檔在尋找答案。

官方文檔已經很清楚地說明了,如果你傳入的參數為浮點數,并且這個浮點值在計算機里面不能被精確存儲,那么它會先被轉換為一個不精確的二進制值,然后再把這個不精確的二進制值轉換為等效的十進制值

對于不能精確表示的小數,當你傳入的時候,Python在拿到這個數前,這個數就已經被轉成了一個不精確的數了。所以你雖然參數傳入的是11.245,但是Python拿到的實際上是11.244999999999...

但是如果你傳入的是字符串"11.245",那么Python拿到它的時候,就能知道這是11.245,不會提前被轉換為一個不精確的值,所以,建議給Decimal的第一個參數傳入字符串型的浮點數,而不是直接寫浮點數。

總結,如果想實現精確的四舍五入,代碼應該這樣寫:

from decimal import Decimal, ROUND_HALF_UP

origin_num = Decimal("11.245")
answer_num = origin_num.quantize(Decimal("0.00"), rounding=ROUND_HALF_UP)
print(answer_num)

運行效果如下圖所示:

特別注意,一旦要做精確計算,那么就不應該再多帶帶使用浮點數,而是應該總是使用Decimal("浮點數")。否則,當你賦值的時候,精度已經被丟失了,建議全程使用Decimal舉例:

a = Decimal("0.1")
b = Decimal("0.2")
c = a + b
print(c)

最后,如果有同學想知道為什么0.125和0.375能被精確的儲存,而1.115、11.245不能被精確儲存,請在這篇文章下面留言,如果想知道的同學多,我就寫一篇文章來說明。

如果這篇文章對你有幫助,請考慮關注我的微信公眾號 未聞Code:

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/43492.html

相關文章

  • 個人整理, 閱讀過的好文章 (每天隨時更新)

    摘要:大家有好的文章可以在評論下面分享出來共同進步本文鏈接數組使用之道程序員進階學習書籍參考指南教你在不使用框架的情況下也能寫出現代化代碼巧用數組函數框架中間件實現沒錯,這就是面向對象編程設計模式需要遵循的個基本原則令人困惑的在中使用協程實現多任 大家有好的文章,可以在評論下面分享出來, 共同進步! 本文github鏈接 php PHP 數組使用之道 PHP程序員進階學習書籍參考指南 教你...

    Chiclaim 評論0 收藏0
  • Java和Python中的整數除法,取余,舍入

    摘要:整數除法對兩個不能整除的整數做除法,就要面對舍入的問題。中的舍入除了缺省的舍入方式,還有多種舍入可供選擇。就是說,我們輸入的十進制數,在計算機內部都是用二進制來表示的。 關于除法,你也許覺得沒什么值得談論的,畢竟小學的時候體育老師就教過我們了。然而對于編程中使用的除法,我覺得還是有很多值得注意的細節的。為什么我想深究一下?因為我日常主要使用Java和Python編程,而它們的除法在細節...

    hosition 評論0 收藏0
  • Java和Python中的整數除法,取余,舍入

    摘要:整數除法對兩個不能整除的整數做除法,就要面對舍入的問題。中的舍入除了缺省的舍入方式,還有多種舍入可供選擇。就是說,我們輸入的十進制數,在計算機內部都是用二進制來表示的。 關于除法,你也許覺得沒什么值得談論的,畢竟小學的時候體育老師就教過我們了。然而對于編程中使用的除法,我覺得還是有很多值得注意的細節的。為什么我想深究一下?因為我日常主要使用Java和Python編程,而它們的除法在細節...

    lentoo 評論0 收藏0
  • Python基礎之(一)基本數據類型

    摘要:但是在轉化中,浮點數轉化為二進制后,不會精確等于十進制的。一般情況下,只要簡單地將最終顯示的結果用四舍五入到所期望的十進制位數,就會得到期望的最終結果。四舍五入內建函數。在中的第二個數,表示要保留的小數位數,返回值是一個四舍五入之后的數值。 數字 基本類型 首先,進入Python交互模式中: //整數 >>> 3 3 //長整數 >>> 3333333333333333333333...

    yagami 評論0 收藏0

發表評論

0條評論

Object

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<