王新勇
高中信息技術(shù)新教材注重理論與實(shí)踐的結(jié)合以及學(xué)科本身的科學(xué)性和理論性,并且以實(shí)現(xiàn)信息意識(shí)、計(jì)算思維、數(shù)字化學(xué)習(xí)與創(chuàng)新以及信息社會(huì)責(zé)任四個(gè)核心素養(yǎng)的提升為目標(biāo)。筆者以Python的round()函數(shù)作為切入點(diǎn),對(duì)數(shù)據(jù)與計(jì)算的關(guān)系和深層鏈接進(jìn)行探究。文章中涉及Python的語(yǔ)法規(guī)則均以Python3為基礎(chǔ),代碼運(yùn)行環(huán)境為python3.8.5版本。
● 發(fā)現(xiàn)問(wèn)題
1.round()函數(shù)的概念
round()函數(shù)為Python內(nèi)置(built-in)的函數(shù),Python安裝完成后即具有該函數(shù)的功能,不需要再引入額外的模塊。round()函數(shù)提供了低精度的四舍五入的功能,需要重點(diǎn)理解低精度以及四舍五入的原則。
2.round()函數(shù)的參數(shù)
round()函數(shù)提供了兩個(gè)參數(shù),round(x, n),其中參數(shù)x可以是整型(int)、實(shí)型(float)或布爾型(bool)的數(shù)值,不能是字符串、列表或字典等數(shù)據(jù)結(jié)構(gòu)類型的值。參數(shù)n是一個(gè)整數(shù)值,為可選參數(shù),用來(lái)表示小數(shù)點(diǎn)后保留的位數(shù),如round(1.233,2),值為1.23,即小數(shù)點(diǎn)后保留2位。參數(shù)n可以為負(fù)數(shù),當(dāng)n為負(fù)數(shù)時(shí),相當(dāng)于對(duì)整數(shù)的第n位(-1,對(duì)應(yīng)個(gè)位)進(jìn)行四舍五入,如round(1123,-2),值為1100,如圖1所示。n為負(fù)整數(shù)的情況,非重點(diǎn)探究?jī)?nèi)容,不做討論。
3.round()函數(shù)取整實(shí)驗(yàn)
基于Python的IDLE交互式Shell工具,進(jìn)行round()函數(shù)的取整實(shí)驗(yàn),如圖2所示。
對(duì)于round(1.3)和round(1.7),是符合四舍五入的原則的。對(duì)于round(1.5)和round(2.5),結(jié)果為什么都是2?round(3.5)和round(4.5)結(jié)果為什么都是4?這是需要思考和探究的第一個(gè)問(wèn)題。
● 追本溯源
1.Python版本差異
如下頁(yè)圖3所示,round()函數(shù)在Python3.0版本相比Python2的變化,主要內(nèi)容包括如下幾點(diǎn):①round()函數(shù)從Python3.0開(kāi)始,對(duì)于0.5、1.5、2.5這類小數(shù)部分值為0.5的float類型數(shù)值,取整時(shí)是舍入到偶數(shù)的一邊。例如,round(2.5),值為2;round(1.5),值也是2。以1.5為例,由于1.5與1和2的距離是一樣的,都是0.5的差值,因此,在Python3.0版本開(kāi)始遵循親偶數(shù)邊取整的原則,我們稱之為親偶性。②對(duì)于round(x)函數(shù)中只有一個(gè)參數(shù)x的情況,是取整操作,則返回int整型。例如,round(1.555),返回值為2,類型為int。③對(duì)于round(x,n)函數(shù)中包括兩個(gè)參數(shù)x和n的情況,返回值的類型,與參數(shù)x的類型一致,不再是Python2版本中定義的統(tǒng)一返回float類型。例如,round(1,2)返回1,類型為int;round(1.000,2),則返回1.0(等同于1.00),類型為float,如圖4所示。
2.round()函數(shù)取整總結(jié)
根據(jù)上述Python3版本的變更分析,可以總結(jié)得出round(x)函數(shù)的特點(diǎn)為“四舍六入五親偶”。這里的四舍六入較好理解,對(duì)于五親偶,即針對(duì)0.5,1.5,2.5這類小數(shù)部分值為0.5的float類型數(shù)值,通過(guò)round(x)函數(shù)取整時(shí),結(jié)果是舍入到偶數(shù)的一邊。對(duì)于round(1.5)和round(2.5)的返回值都為2的問(wèn)題,已經(jīng)找到了答案。
● 問(wèn)題拓展
通過(guò)round()函數(shù)進(jìn)行float類型數(shù)值的保留小數(shù)位數(shù)的四舍五入實(shí)驗(yàn),發(fā)現(xiàn)如下問(wèn)題:兩個(gè)數(shù)值的小數(shù)部分都是0.675,保留兩位小數(shù)的四舍五入結(jié)果為什么不一樣呢(如圖5)?帶著這樣的問(wèn)題,思考float類型數(shù)值在計(jì)算機(jī)中是如何表示的,進(jìn)一步探究float類型的浮動(dòng)本質(zhì)。
● 浮動(dòng)本質(zhì)
以0.4和100.4為例,通過(guò)print()函數(shù)設(shè)置參數(shù)“%.30f”格式化輸出30位小數(shù)的方式,來(lái)觀察Python3的float數(shù)值的真實(shí)值表示,與原始值相同的部分為17位有效數(shù)字,如圖6和圖7所示。
0.4格式化輸出30位小數(shù)的數(shù)值中紅框內(nèi)的17位有效數(shù)字,小數(shù)部分占了16位,整數(shù)部分為0,占了1位。100.4格式化輸出30位小數(shù)的數(shù)值中紅框內(nèi)的17位有效數(shù)字,小數(shù)部分占了14位,整數(shù)部分為100,占了3位。Python3中float類型數(shù)值的精度為17位有效數(shù)字。如圖8所示,Python3版本基于IEEE-754中對(duì)浮點(diǎn)數(shù)的定義,確定了17位有效數(shù)字來(lái)表示float類型數(shù)值。
通過(guò)float類型數(shù)值的判等運(yùn)算,也可以驗(yàn)證17位有效數(shù)字的精度控制,進(jìn)一步理解float類型數(shù)值的浮動(dòng)本質(zhì)。對(duì)于float類型的數(shù)值比較,Python只會(huì)取其前17位有效數(shù)字的值進(jìn)行比較,17位有效數(shù)字包括整數(shù)和小數(shù)部分。如下頁(yè)圖9所示,0.4與0.4000000000000001(小數(shù)部分的第16位值為1)進(jìn)行判等比較值為False,是因?yàn)?.4等價(jià)于0.4000000000000000,第16位值為0,而0.4與0.40000000000000001(小數(shù)部分第17位值為1)和0.40000000000000002(小數(shù)部分第17位值為2)判等為True,則是因?yàn)榍?7位有效數(shù)字部分的值是相同的,小數(shù)部分精度范圍外的值不參與比較運(yùn)算。
● 刨根問(wèn)底
精度范圍外的數(shù)值是如何產(chǎn)生的?如下頁(yè)圖10所示,0.675小數(shù)點(diǎn)后第17位~第30位的值,是如何產(chǎn)生的?需要從float類型的十進(jìn)制數(shù)值轉(zhuǎn)二進(jìn)制的過(guò)程來(lái)探究。
1.float類型數(shù)值轉(zhuǎn)換為二進(jìn)制
轉(zhuǎn)換原則:乘2取整,直到小數(shù)部分值為0,則轉(zhuǎn)換完成。以數(shù)值0.125為例,轉(zhuǎn)換為二進(jìn)制的過(guò)程如下頁(yè)圖11所示。