成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

Object / 2089人閱讀

摘要:網(wǎng)上有人說(shuō),因?yàn)樵谟?jì)算機(jī)里面,小數(shù)是不精確的,例如在計(jì)算機(jī)中實(shí)際上是,所以當(dāng)你對(duì)這個(gè)小數(shù)精確到小數(shù)點(diǎn)后兩位的時(shí)候,實(shí)際上小數(shù)點(diǎn)后第三位是,所以四舍五入,因此結(jié)果為。

今天又有一個(gè)Python初學(xué)者被中文技術(shù)博客中的垃圾文章給誤導(dǎo)了。

這位初學(xué)者的問(wèn)題是:

在Python中,如何精確地進(jìn)行浮點(diǎn)數(shù)的四舍五入,保留兩位小數(shù)?

如果你在Google或者百度上搜索,你會(huì)發(fā)現(xiàn)大量的來(lái)自CSDN或者簡(jiǎn)書(shū)上面的文章講到這一點(diǎn),但是他們的說(shuō)法無(wú)外乎下面幾種:

連例子都不舉的垃圾文章

如下圖所示,懶得吐槽。

使用round函數(shù)

他們舉的例子為:

>>> round(1.234, 2)
1.23

這種文章,他只演示了四舍,但是卻沒(méi)有演示五入。所以如果你代碼稍作修改,就會(huì)發(fā)現(xiàn)有問(wèn)題:

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

這種文章稍微好一點(diǎn),知道多舉幾個(gè)例子:

然而這種文章也是漏洞百出,只要你多嘗試幾個(gè)數(shù)字就會(huì)發(fā)現(xiàn)問(wèn)題,在Python 2和Python 3下面,效果是不一樣的。先來(lái)看看Python 2下面的運(yùn)行效果:

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

再來(lái)看看Python 3下面的效果:

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

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

裝逼貨

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

不過(guò)他的使用方法,大家看他吧

具體原因不詳 ????

不推薦使用這個(gè)方法???

這種人要先裝個(gè)逼,表示自己知道有這樣一個(gè)庫(kù),但是用起來(lái)發(fā)現(xiàn)有問(wèn)題,而且不知道原因,所以不建議大家使用。

decimal是專門(mén)為高精度計(jì)算用的模塊,他竟然說(shuō)不建議大家使用???

round到底出了什么問(wèn)題?

罵完了,我們來(lái)說(shuō)說(shuō),在Python 3里面,round這個(gè)內(nèi)置的函數(shù)到底有什么問(wèn)題。

網(wǎng)上有人說(shuō),因?yàn)樵谟?jì)算機(jī)里面,小數(shù)是不精確的,例如1.115在計(jì)算機(jī)中實(shí)際上是1.1149999999999999911182,所以當(dāng)你對(duì)這個(gè)小數(shù)精確到小數(shù)點(diǎn)后兩位的時(shí)候,實(shí)際上小數(shù)點(diǎn)后第三位是4,所以四舍五入,因此結(jié)果為1.11

這種說(shuō)法,對(duì)了一半。

因?yàn)椴⒉皇撬械男?shù)在計(jì)算機(jī)中都是不精確的。例如0.125這個(gè)小數(shù)在計(jì)算機(jī)中就是精確的,它就是0.125,沒(méi)有省略后面的值,沒(méi)有近似,它確確實(shí)實(shí)就是0.125

但是如果我們?cè)赑ython中把0.125精確到小數(shù)點(diǎn)后兩位,那么它的就會(huì)變成0.12

>>> round(0.125, 2)
0.12

為什么在這里四舍了?

還有更奇怪的,另一個(gè)在計(jì)算機(jī)里面能夠精確表示的小數(shù)0.375,我們來(lái)看看精確到小數(shù)點(diǎn)后兩位是多少:

>>> round(0.375, 2)
0.38

為什么這里又五入了?

因?yàn)樵赑ython 3里面,round對(duì)小數(shù)的精確度采用了四舍六入五成雙的方式。

如果你寫(xiě)過(guò)大學(xué)物理的實(shí)驗(yàn)報(bào)告,那么你應(yīng)該會(huì)記得老師講過(guò),直接使用四舍五入,最后的結(jié)果可能會(huì)偏高。所以需要使用奇進(jìn)偶舍的處理方法。

例如對(duì)于一個(gè)小數(shù)a.bcd,需要精確到小數(shù)點(diǎn)后兩位,那么就要看小數(shù)點(diǎn)后第三位:

如果d小于5,直接舍去

如果d大于5,直接進(jìn)位

如果d等于5:

d后面沒(méi)有數(shù)據(jù),且c為偶數(shù),那么不進(jìn)位,保留c

d后面沒(méi)有數(shù)據(jù),且c為奇數(shù),那么進(jìn)位,c變成(c + 1)

如果d后面還有非0數(shù)字,例如實(shí)際上小數(shù)為a.bcdef,此時(shí)一定要進(jìn)位,c變成(c + 1)

關(guān)于奇進(jìn)偶舍,有興趣的同學(xué)可以在維基百科搜索這兩個(gè)詞條:數(shù)值修約奇進(jìn)偶舍

所以,round給出的結(jié)果如果與你設(shè)想的不一樣,那么你需要考慮兩個(gè)原因:

你的這個(gè)小數(shù)在計(jì)算機(jī)中能不能被精確儲(chǔ)存?如果不能,那么它可能并沒(méi)有達(dá)到四舍五入的標(biāo)準(zhǔn),例如1.115,它的小數(shù)點(diǎn)后第三位實(shí)際上是4,當(dāng)然會(huì)被舍去。

如果你的這個(gè)小數(shù)在計(jì)算機(jī)中能被精確表示,那么,round采用的進(jìn)位機(jī)制是奇進(jìn)偶舍,所以這取決于你要保留的那一位,它是奇數(shù)還是偶數(shù),以及它的下一位后面還有沒(méi)有數(shù)據(jù)。

如何正確進(jìn)行四舍五入

如果要實(shí)現(xiàn)我們數(shù)學(xué)上的四舍五入,那么就需要使用decimal模塊。

如何正確使用decimal模塊呢?

看官方文檔,不要看中文垃圾博客?。。?/p>

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

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

不要擔(dān)心看不懂英文,Python已經(jīng)推出了官方中文文檔(有些函數(shù)的使用方法還沒(méi)有翻譯完成)。

我們來(lái)看一下:https://docs.python.org/zh-cn...

官方文檔給出了具體的寫(xiě)法:

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

那么我們來(lái)測(cè)試一下,0.1250.375分別保留兩位小數(shù)是多少:

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

怎么結(jié)果和round一樣?我們來(lái)看看文檔中quantize的函數(shù)原型和文檔說(shuō)明:

這里提到了可以通過(guò)指定rounding參數(shù)來(lái)確定進(jìn)位方式。如果沒(méi)有指定rounding參數(shù),那么默認(rèn)使用上下文提供的進(jìn)位方式。

現(xiàn)在我們來(lái)查看一下默認(rèn)上下文中的進(jìn)位方式是什么:

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

如下圖所示:

ROUND_HALF_EVEN實(shí)際上就是奇進(jìn)偶舍!如果要指定真正的四舍五入,那么我們需要在quantize中指定進(jìn)位方式為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")

現(xiàn)在看起來(lái)一切都正常了。

那么會(huì)不會(huì)有人進(jìn)一步追問(wèn)一下,如果Decimal接收的參數(shù)不是字符串,而是浮點(diǎn)數(shù)會(huì)怎么樣呢?

來(lái)實(shí)驗(yàn)一下:

>>> 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")

那是不是說(shuō)明,在Decimal的第一個(gè)參數(shù),可以直接傳浮點(diǎn)數(shù)呢?

我們換一個(gè)數(shù)來(lái)測(cè)試一下:

>>> 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")

為什么浮點(diǎn)數(shù)11.245和字符串"11.245",傳進(jìn)去以后,結(jié)果不一樣?

我們繼續(xù)在文檔在尋找答案。

官方文檔已經(jīng)很清楚地說(shuō)明了,如果你傳入的參數(shù)為浮點(diǎn)數(shù),并且這個(gè)浮點(diǎn)值在計(jì)算機(jī)里面不能被精確存儲(chǔ),那么它會(huì)先被轉(zhuǎn)換為一個(gè)不精確的二進(jìn)制值,然后再把這個(gè)不精確的二進(jìn)制值轉(zhuǎn)換為等效的十進(jìn)制值。

對(duì)于不能精確表示的小數(shù),當(dāng)你傳入的時(shí)候,Python在拿到這個(gè)數(shù)前,這個(gè)數(shù)就已經(jīng)被轉(zhuǎn)成了一個(gè)不精確的數(shù)了。所以你雖然參數(shù)傳入的是11.245,但是Python拿到的實(shí)際上是11.244999999999...。

但是如果你傳入的是字符串"11.245",那么Python拿到它的時(shí)候,就能知道這是11.245,不會(huì)提前被轉(zhuǎn)換為一個(gè)不精確的值,所以,建議給Decimal的第一個(gè)參數(shù)傳入字符串型的浮點(diǎn)數(shù),而不是直接寫(xiě)浮點(diǎn)數(shù)。

總結(jié),如果想實(shí)現(xiàn)精確的四舍五入,代碼應(yīng)該這樣寫(xiě):

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)

運(yùn)行效果如下圖所示:

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

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

最后,如果有同學(xué)想知道為什么0.125和0.375能被精確的儲(chǔ)存,而1.115、11.245不能被精確儲(chǔ)存,請(qǐng)?jiān)谶@篇文章下面留言,如果想知道的同學(xué)多,我就寫(xiě)一篇文章來(lái)說(shuō)明。

如果這篇文章對(duì)你有幫助,請(qǐng)考慮關(guān)注我的微信公眾號(hào) 未聞Code:

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/43492.html

相關(guān)文章

  • 個(gè)人整理, 閱讀過(guò)的好文章 (每天隨時(shí)更新)

    摘要:大家有好的文章可以在評(píng)論下面分享出來(lái)共同進(jìn)步本文鏈接數(shù)組使用之道程序員進(jìn)階學(xué)習(xí)書(shū)籍參考指南教你在不使用框架的情況下也能寫(xiě)出現(xiàn)代化代碼巧用數(shù)組函數(shù)框架中間件實(shí)現(xiàn)沒(méi)錯(cuò),這就是面向?qū)ο缶幊淘O(shè)計(jì)模式需要遵循的個(gè)基本原則令人困惑的在中使用協(xié)程實(shí)現(xiàn)多任 大家有好的文章,可以在評(píng)論下面分享出來(lái), 共同進(jìn)步! 本文github鏈接 php PHP 數(shù)組使用之道 PHP程序員進(jìn)階學(xué)習(xí)書(shū)籍參考指南 教你...

    Chiclaim 評(píng)論0 收藏0
  • Java和Python中的整數(shù)除法,取余,舍入

    摘要:整數(shù)除法對(duì)兩個(gè)不能整除的整數(shù)做除法,就要面對(duì)舍入的問(wèn)題。中的舍入除了缺省的舍入方式,還有多種舍入可供選擇。就是說(shuō),我們輸入的十進(jìn)制數(shù),在計(jì)算機(jī)內(nèi)部都是用二進(jìn)制來(lái)表示的。 關(guān)于除法,你也許覺(jué)得沒(méi)什么值得談?wù)摰?,畢竟小學(xué)的時(shí)候體育老師就教過(guò)我們了。然而對(duì)于編程中使用的除法,我覺(jué)得還是有很多值得注意的細(xì)節(jié)的。為什么我想深究一下?因?yàn)槲胰粘V饕褂肑ava和Python編程,而它們的除法在細(xì)節(jié)...

    hosition 評(píng)論0 收藏0
  • Java和Python中的整數(shù)除法,取余,舍入

    摘要:整數(shù)除法對(duì)兩個(gè)不能整除的整數(shù)做除法,就要面對(duì)舍入的問(wèn)題。中的舍入除了缺省的舍入方式,還有多種舍入可供選擇。就是說(shuō),我們輸入的十進(jìn)制數(shù),在計(jì)算機(jī)內(nèi)部都是用二進(jìn)制來(lái)表示的。 關(guān)于除法,你也許覺(jué)得沒(méi)什么值得談?wù)摰?,畢竟小學(xué)的時(shí)候體育老師就教過(guò)我們了。然而對(duì)于編程中使用的除法,我覺(jué)得還是有很多值得注意的細(xì)節(jié)的。為什么我想深究一下?因?yàn)槲胰粘V饕褂肑ava和Python編程,而它們的除法在細(xì)節(jié)...

    lentoo 評(píng)論0 收藏0
  • Python基礎(chǔ)之(一)基本數(shù)據(jù)類型

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

    yagami 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

Object

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<