Python二級——浮點型數值計算
Python二級——浮點型數值計算
引言
在python二級考試中,有這樣的題目:
print(0.1 + 0.2 == 0.3)
答案是False
對於初學計算機語言的人來說可能很奇怪,難道0.1+0.2不是等於0.3?當然也不是,但這就涉及到計算機語言的浮點型底層儲存。
個位小數的加減法失真
先編寫程式碼看看個位小數的加減法
for i in range(1,10):
for m in range(1,i+1):
a='0.{}'.format(i)
b='0.{}'.format(m)
c= eval(a)+eval(b)
print('{}+{}={}'.format(a,b,c),end=' ')
print('')
for i in range(2,10):
for m in range(1,i):
a='0.{}'.format(i)
b='0.{}'.format(m)
c=eval(a)-eval(b)
print('{}-{}={}'.format(a,b,c),end=' ')
print('')
輸出結果為
可以看到僅僅是個位小數的加減法,都有如此多的失真情況。
如果只是應對python的二級考試,只需要再編寫程式碼,將其中的失真的找出來就好了
for i in range(1,10):
for m in range(1,i+1):
a='0.{}'.format(i)
b='0.{}'.format(m)
c=eval(a)+eval(b)
if c != round(c,1):
print('{}+{}={}'.format(a,b,c))
for i in range(2,10):
for m in range(1,i):
a= '0.{}'.format(i)
b='0.{}'.format(m)
c=eval(a)-eval(b)
if c != round(c,1):
print('{}-{}={}'.format(a,b,c))
執行結果:
0.2+0.1=0.30000000000000004
0.4+0.2=0.6000000000000001
0.6+0.3=0.8999999999999999
0.7+0.1=0.7999999999999999
0.7+0.2=0.8999999999999999
0.7+0.6=1.2999999999999998
0.8+0.4=1.2000000000000002
0.9+0.8=1.7000000000000002
0.3-0.1=0.19999999999999998
0.3-0.2=0.09999999999999998
0.4-0.1=0.30000000000000004
0.4-0.3=0.10000000000000003
0.5-0.4=0.09999999999999998
0.6-0.2=0.39999999999999997
0.6-0.4=0.19999999999999996
0.6-0.5=0.09999999999999998
0.7-0.2=0.49999999999999994
0.7-0.3=0.39999999999999997
0.7-0.4=0.29999999999999993
0.7-0.5=0.19999999999999996
0.7-0.6=0.09999999999999998
0.8-0.1=0.7000000000000001
0.8-0.2=0.6000000000000001
0.8-0.5=0.30000000000000004
0.8-0.6=0.20000000000000007
0.8-0.7=0.10000000000000009
0.9-0.3=0.6000000000000001
0.9-0.6=0.30000000000000004
0.9-0.7=0.20000000000000007
0.9-0.8=0.09999999999999998
貌似有點多,這選擇題的一分,咋不要也罷,不過還是要記住幾個常見的加法失真的情況。
失真原因:float數值二進位制運算
計算機是二進位制的資料,int型別進位制之間的轉化起來十分簡單與準確,但是float型別資料轉化為二進位制就比較麻煩。
- 浮點數儲存
浮點數在計算機中儲存也是以二進位制的形式,遵循IEEE二進位制算數標準;格式為:
float : 符號位(首位)、指數位(8位)、尾數(23位)
double:符號位(首位)、指數位(11位)、尾數(52位)
- 十進位制浮點數轉換為二進位制
★方法:
⑴整數部分:除以2,取出餘數,商繼續除以2,直到得到0為止,將取出的餘數逆序
⑵小數部分:乘以2,然後取出整數部分,將剩下的小數部分繼續乘以2,然後再取整數部分,一直取到小數部分為零為止。
如果永遠不為零,則按要求保留足夠位數的小數,最後一位做0舍1入。將取出的整數順序排列。
★示例:22.8125
⑴整數部分:除以2,商繼續除以2,得到0為止,將餘數逆序排列。
22 / 2 商11 餘 0
11 / 2 商5 餘 1
5 / 2 商2 餘 1
2 / 2 商1 餘 0
1 /2 商0 餘 1
得到22的二進位制是 : 10110
⑵小數部分:乘以2,取整,小數部分繼續乘以2,取整,得到小數部分0為止,將整數順序排列。
0.8125x2=1.625 取整1 小數部分是0.625
0.625x2=1.25 取整1 小數部分是0.25
0.25x2=0.5 取整0 小數部分是0.5
0.5x2=1.0 取整1 小數部分是0
得到0.8125的二進位制是 : 0.1101
⑶結果:十進位制:22.8125 等於二進位制: 10110.1101
由此可知,當浮點數化成的分數的分母部分是2的倍數時,才有可能完全精度轉化二進位制數,所以在計算的時候會出現失真情況。