使用math.modf()對一個浮點數進行拆分時經常會遇到如下情況
如下
import math
print(math.modf(2.4)) # 輸出 (0.3999999999999999, 2.0)
我們會發現對2.4進行拆分得到的小數并不是0.4,這是因為什么呢?
這是因為計算機采用的是二進制代碼,而二進制代碼由于計算上的誤差無法準確表示某些十進制數的小數部分。
下面我們具體來講一下。
我們知道一個十進制數轉化為二進制數需要分為兩部分進行計算:整數部分和小數部分。
整數部分采用“除二取余法”。將這個整數除以2,得到它的余數,然后將商再除以3,直到商為0為止,并將各個得到的余數按照相反的順序進行排列。
小數部分采用“乘2取整法”,將這個小數乘2,將新得到的數的整數部分取出,再用2乘余下的小數部分,如此往復直到乘積中的小數部分為0或者達到要求的精度為止。并將取出的整數部分按照取出的先后順序從前到后排列。
123/2=61...1
61/2=30...1
30/2=15...0
15/2=7...1
7/2=3...1
3/2=1...1
1/2=0...1
(123)10=(1111011)2
0.4*2=0.8...0
0.8*2=1.6...1
0.6*2=1.2...1
0.2*2=0.4...0
0.4*2=0.8...0
0.8*2=1.6...1
0.6*2=1.2...1
(0.4)10=(0.011001100110011001100110...)2
(123.4)2=(1111011.011001100110011...)2
十進制的0.4轉化為二進制時會出現重復循環“0110”的情況,但是目前計算機存儲浮點數是按照電器和電子工程師協會的標準(IEEE754浮點數存儲格式標準)來進行存儲的。
IEEE規定單精度浮點最多存儲32位(4個字節):
31位是符號位。1表示該數為負,0為正
30~23是指數位(-128-127)
22~0是尾數位,尾數的編碼一般是源碼和補碼
IEEE標準從邏輯上用三元組{S,E,M}表示一個數,如圖所示:

也就是說上面將0.4轉換出的二進制代碼,我們只能存儲23位,即使數據類型為double,也只能存儲52位,這樣大家便能看出問題出現的原因了。23位的數據顯然無法完整表示0.4的二進制數據,于是誤差產生了。
那所有的十進制小數都無法完整表示嗎?不是的,只要小數部分乘上2最終小數部分能夠得到0就不會出現這種問題,比如0.5,0.75。
import math
print(math.modf(1.5)) # 輸出 (0.5,1.0)
0.5*2=1...1
(0.5)10=(0.1)2
0.75*2=1.5...1
0.5*2=1...1
(0.75)10=(0.11)2
補充:Python中“取整”的各種問題
一、初衷:
有時候我們分頁展示數據的時候,需要計算頁數。一般都是向上取整,例如counts=205 pageCouts=20 ,pages= 11 頁。
一般的除法只是取整數部分,達不到要求。
二、方法:
1、通用除法:
取臨界值,計算下A+B-1的范圍就OK.
2 、Python除法:
首先要說的是python中的除法運算,
當使用x/y形式進行除法運算時,那么會進行所謂的true除法,比如2.0/3的結果是 0.66666666666666663。
另外一種除法是采用x//y的形式(向下取整),那么這里采用的是所謂floor除法,即得到不大于結果的最大整數值,這個運算時與操作數無關的。比如2//3的結果是0,-2//3的結果是-1,-2.0//3的結果是-1.0。
在python 3.0中,x/y將只執行true除法,而與操作數無關;x//y則執行floor除法。
Python運算向上取整方法:(A+B-1)/B
3、Python match.ceil函數 np.ceil函數
ceil(x)函數是向上取整,即取大于等于x的最接近整數。
import math
math.ceil(float(205)/20)
import numpy as np
np.ceil(float(205)/20)
Python 向上取整的算法
1、一般使用floor除法 (np.floor()或者math.floor())
import numpy as np
n = np.array([-1.7, -2.5, -0.2, 0.6, 1.2, 2.7, 11])
floor = np.floor(n)
print(floor) # [ -2. -3. -1. 0. 1. 2. 11.]
2、一般除法/
A=100
B=16
c=100//16
(c=6)
3、round()四舍五入函數。
np.around 返回四舍五入后的值,可指定精度。
around(a, decimals=0, out=None)
a 輸入數組
decimals 要舍入的小數位數。 默認值為0。 如果為負,整數將四舍五入到小數點左側的位置
import numpy as np
n = np.array([-0.746, 4.6, 9.4, 7.447, 10.455, 11.555])
around1 = np.around(n)
print(around1) # [ -1. 5. 9. 7. 10. 12.]
around2 = np.around(n, decimals=1)
print(around2) # [ -0.7 4.6 9.4 7.4 10.5 11.6]
around3 = np.around(n, decimals=-1)
print(around3) # [ -0. 0. 10. 10. 10. 10.]
Python 分別取整的算法
math模塊中的 modf()方法
將整數部分和小數部分分別取出,可以使用math模塊中的 modf()方法
例如:
>>> math.modf(4.25)
(0.25, 4.0)
>>> math.modf(4.33)
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
您可能感興趣的文章:- OpenCV-Python實現通用形態學函數
- python通過函數名調用函數的幾種方法總結
- Python量化交易實戰之使用Resample函數轉換“日K”數據
- Python函數裝飾器的使用教程
- 淺談Python中的函數(def)及參數傳遞操作
- Python基礎之函數嵌套知識總結
- python 定義函數 返回值只取其中一個的實現
- 這三個好用的python函數你不能不知道!