Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法_第1頁(yè)
Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法_第2頁(yè)
Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法_第3頁(yè)
Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法_第4頁(yè)
Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法_第5頁(yè)
已閱讀5頁(yè),還剩4頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法目錄1.取整的三種方法1.1強(qiáng)轉(zhuǎn)int類型1.2采用math.ceil和math.floor1.3采用round2.格式化浮點(diǎn)數(shù)輸出3.執(zhí)行精確的小數(shù)計(jì)算4.無(wú)窮大、負(fù)無(wú)窮大和NaN的判斷測(cè)試參考強(qiáng)轉(zhuǎn)int類型會(huì)直接對(duì)浮點(diǎn)數(shù)的小數(shù)部分進(jìn)行截?cái)啵o(wú)論是正還是負(fù))。還有一種方法是math.ceil和math.floor。無(wú)論是正數(shù)還是負(fù)數(shù),都遵循:ceil往數(shù)軸正方向取整,floor往數(shù)軸負(fù)方向取整。round原型為round(value,ndigits),可以將一個(gè)浮點(diǎn)數(shù)取整到固定的小數(shù)位。該函數(shù)對(duì)正數(shù)和負(fù)數(shù)都采取就近取整原則,而當(dāng)某個(gè)值恰好等于兩個(gè)整數(shù)間一半時(shí),取整操作會(huì)取到離該值最近的那個(gè)偶數(shù)。

1.取整的三種方法

1.1強(qiáng)轉(zhuǎn)int類型

這種方法會(huì)直接對(duì)浮點(diǎn)數(shù)的小數(shù)部分進(jìn)行截?cái)啵o(wú)論是正還是負(fù))。

print(int(2.7))#2

print(int(-2.7))#-2

1.2采用math.ceil和math.floor

這種方法的取整規(guī)則如下圖所示:

可以看到無(wú)論是正數(shù)還是負(fù)數(shù),都遵循:ceil往數(shù)軸正方向取整,floor往數(shù)軸負(fù)方向取整。實(shí)例如下:

print(math.ceil(-1.27))#-1

print(math.floor(-1.27))#-2

print(math.ceil(1.27))#2

print(math.floor(1.27))#1

1.3采用round

round原型為round(value,ndigits),可以將一個(gè)浮點(diǎn)數(shù)取整到固定的小數(shù)位。該函數(shù)對(duì)正數(shù)和負(fù)數(shù)都采取就近取整原則,而當(dāng)某個(gè)值恰好等于兩個(gè)整數(shù)間一半時(shí),取整操作會(huì)取到離該值最近的那個(gè)偶數(shù)。像1.5和2.5這樣的值都會(huì)取整到2。示例如下:

print(round(1.23,0))#1.0

print(round(1.23,1))#1.2

print(round(1.27,1))#1.3

print(round(-1.27,1))#-1.3

print(round(1.25361,3))#1.254

print(round(1.5,0))#2.0

print(round(2.5,0))#2.0

傳遞給round()參數(shù)ndigits可以是負(fù)數(shù),這種情況下回相應(yīng)取整到十位、百位、千位:

a=1627731

print(round(a,-1))#1627730

print(round(a,-2))#1627700

print(round(a,-3))#1628000

2.格式化浮點(diǎn)數(shù)輸出

注意對(duì)值輸出時(shí)別把取整和格式化操作混為一談。如果只是將數(shù)值以固定位數(shù)輸出,一般是用不著round()的,只要在用format格式化時(shí)指定所需要的精度即可(format()格式化操作會(huì)根據(jù)round()的規(guī)則進(jìn)行取整,最終返回一個(gè)字符串類型)。

x=1234.56789

s=format(x,"0.2f")

print(type(s),format(x,"0.2f"))#class'str'1234.57

除了取整到固定小數(shù)位,format()還具有許多格式化功能,如格式化輸出對(duì)齊,增加千分位分隔符等。實(shí)際上面的0.2f就表示至少對(duì)齊到0個(gè)字符(相當(dāng)于沒(méi)有對(duì)齊操作),并保留兩位小數(shù)。

小提示:.2f也表示至少對(duì)齊到0個(gè)字符(默認(rèn)是0),并保留兩位小數(shù),

和0.2f二者是等效的。

更多示例如下:

#往右調(diào)整以對(duì)齊到10個(gè)字符

print(format(x,"10.1f"))#1234.6

#往右調(diào)整以對(duì)齊到10個(gè)字符

print(format(x,"10.1f"))#1234.6

#居中以對(duì)齊到10個(gè)字符

print(format(x,"^10.1f"))#1234.6

#增加千位分隔符

print(format(x,","))#1,234.56789

#增加千位分隔符并保存到1位小數(shù)

print(format(x,"0,.1f"))#1,234.6

如果想使用科學(xué)計(jì)數(shù)法,只要把f改成e或E即可:

print(format(x,"e"))#1.234568e+03

print(format(x,"0.2E"))#1.23E+03

此外,我們還可以利用字符串的translate()方法交換不同的分隔符:

swap_separators={ord("."):",",ord(","):"."}

print(format(x,",").translate(swap_separators))#1.234,56789

最后,我們這里提一下,調(diào)用字符串的.format()函數(shù)和單獨(dú)調(diào)用format()函數(shù)可以達(dá)到相同的效果,如:

print("valueis{:0.3f}".format(x))#valueis1.235

print("Thevalueis{:0,.2f}".format(x))#Thevalueis1,234.57

當(dāng)然我們也可以使用%操作符來(lái)對(duì)數(shù)值做格式化處理,如:

print("%.2f"%x)

print("%10.1f"%x)

print("%-10.1f"%x)

這種格式化操作雖然可行,但是比起更加現(xiàn)代化的format()方法,這種方法就顯得不是那么強(qiáng)大了。如用%操作符來(lái)格式化數(shù)值時(shí),有些功能就沒(méi)法得到支持了(如添加千位分隔符)。

3.執(zhí)行精確的小數(shù)計(jì)算

我們?cè)诘谝徊糠纸榻B了round()函數(shù),我們有可能會(huì)企圖用浮點(diǎn)取整的方式來(lái)修正精度上的問(wèn)題,如:

a=2.1

b=4.2

c=a+b

print(c)#6.300000000000001

print(c==6.3)#False

print(round(c,2))#6.3企圖這樣修正精度(???)

對(duì)大部分浮點(diǎn)數(shù)應(yīng)用程序(包括科學(xué)計(jì)算與機(jī)器學(xué)習(xí))來(lái)說(shuō),一般都不必(或者所不推薦)這么做。雖然Python的浮點(diǎn)運(yùn)算會(huì)引入一些小誤差,但這些誤差實(shí)際上是底層CPU的浮點(diǎn)運(yùn)算單元和IEEE754浮點(diǎn)算數(shù)標(biāo)準(zhǔn)的一種特性。由于Python的浮點(diǎn)數(shù)類型保存的數(shù)據(jù)采用的是原始保存形式,因此只要代碼中用到了float實(shí)例,那就無(wú)法避免這樣的誤差。

如果避免出現(xiàn)誤差的行為非常重要(比如在金融應(yīng)用中),那么可以考慮使用decimal模塊。事實(shí)上在用Python做數(shù)據(jù)庫(kù)庫(kù)接口時(shí)經(jīng)常碰到Decimal對(duì)象當(dāng)訪問(wèn)金融數(shù)據(jù)時(shí)尤其如此。我們通過(guò)使用Decimal對(duì)象解決上述問(wèn)題:

fromdecimalimportDecimal

a=Decimal('4.2')

b=Decimal('2.1')

print(type(a+b),a+b)#class'decimal.Decimal'6.3

print((a+b)==Decimal('6.3'))#True

這么做看起來(lái)似乎有點(diǎn)怪異(將數(shù)字以字符串的形式來(lái)指定)。但是Decimal對(duì)象能夠以任何期望的方式來(lái)工作(支持所有常見(jiàn)的數(shù)學(xué)操作)。如果要將它們打印出來(lái)或者在字符串格式化函數(shù)中使用,它們看起來(lái)就和普通數(shù)字一樣。它們也可以和普通int、float類型混合操作(最后會(huì)統(tǒng)一強(qiáng)轉(zhuǎn)為Decimal類型):

print(type(a+1),a+1)#class'decimal.Decimal'5.2

但是需要注意的是不要將其與普通float類型直接進(jìn)行比較:

print((a+b)==6.3)#False

decimal模塊的強(qiáng)大之處在于在計(jì)算過(guò)程中靈活地控制數(shù)字的位數(shù)和四舍五入,如我們可以創(chuàng)建一個(gè)本地的上下文環(huán)境然后修改精度的設(shè)定,如:

fromdecimalimportlocalcontext

a=Decimal("1.3")

b=Decimal("1.7")

print(a/b)#0.7647058823529411764705882353

withlocalcontext()asctx:

ctx.prec=3

print(a/b)#0.765

withlocalcontext()asctx:

ctx.prec=50

print(a/b)#0.764705882352941176470588235294117647058823529

不過(guò)還是我們上面所說(shuō)的,如果我們處理的是科學(xué)或工程類型的問(wèn)題,那么更常見(jiàn)的做法是直接使用普通的float浮點(diǎn)類型。首先,在真實(shí)世界中極少有東西需要計(jì)算到小數(shù)點(diǎn)后17位(float提供17位的精度),因此在計(jì)算中引入的微小誤差不足掛齒;其次,原生的float浮點(diǎn)數(shù)運(yùn)算性能要快許多如果要執(zhí)行大量計(jì)算,性能問(wèn)題就顯得很重要了。

在使用float類型時(shí),我們同樣還需要對(duì)類似相減抵消(substractioncancellation)以及把大數(shù)和小數(shù)加載一起的情況多加小心:

nums=[1.23e+18,1,-1.23e+18]

print(sum(nums))#0.0

使用Decimal對(duì)象當(dāng)然可以解決此問(wèn)題。不過(guò)在不動(dòng)用Decimal對(duì)象的情況下,我們可以使用math.fsum()以更精確的實(shí)現(xiàn)來(lái)解決:

importmath

print(math.fsum(nums))#1.0

但對(duì)于其它復(fù)雜的數(shù)值算法,我們就需要研究算法本身,理解其誤差傳播(errorpropagation)了,這屬于數(shù)值分析的研究范疇。在數(shù)值分析中數(shù)學(xué)家研究了大量數(shù)值算法,其中一些算法的誤差處理能力優(yōu)于其它算法,詳情可以參見(jiàn)我的數(shù)值計(jì)算專欄《orion-orion:數(shù)值計(jì)算》,此處不再詳述。

4.無(wú)窮大、負(fù)無(wú)窮大和NaN的判斷測(cè)試

在實(shí)際項(xiàng)目中我們需要對(duì)浮點(diǎn)數(shù)的無(wú)窮大、負(fù)無(wú)窮大或NaN(notanumber)進(jìn)行判斷測(cè)試。在Python中沒(méi)有特殊的語(yǔ)法來(lái)表示這些特殊的浮點(diǎn)值,但是它們可以通過(guò)float來(lái)創(chuàng)建:

a=float("inf")

b=float("-inf")

c=float("nan")

print(a,b,c)#inf-infnan

要檢查是否出現(xiàn)了這些值,可以使用math.isinf()和math.isnan()函數(shù):

print(math.isinf(a))#True

print(math.isnan(c))#True

這些特殊浮點(diǎn)數(shù)的詳細(xì)信息可以參考IEEE754規(guī)范。但是我們這里有幾個(gè)棘手的問(wèn)題需要搞清楚,尤其是設(shè)計(jì)比較操作和操作符時(shí)可能出現(xiàn)的問(wèn)題。

無(wú)窮大值在數(shù)學(xué)計(jì)算中會(huì)進(jìn)行傳播,如:

a=float("inf")

print(a+45)#inf

print(a*10)#inf

print(10/a)#0.0

但是,某些關(guān)于無(wú)窮大值特定的操作會(huì)導(dǎo)致未定義的行為并產(chǎn)生NaN的結(jié)果,例如:

a=float("inf")

print(a/a)#nan

b=float("-inf")

print(a+b)#nan

NaN會(huì)通過(guò)所有的操作進(jìn)行傳播,且不會(huì)引發(fā)任何異常,如:

c=float("nan")

print(c+23)#nan

print(c/2)#nan

print(c+2)#nan

有關(guān)NaN,一個(gè)微妙的特性是他們?cè)谧霰容^時(shí)從不會(huì)被判定為相等,如:

c=float("nan")

d=float("nan")

print(c==d)#Fals

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論