python 浮點除法


昨天晚上久違地去打了次div2

一年沒打,掛得很慘

早上起來試着用python寫一遍唯一寫出來的a題

然后發現了一個奇怪的現象

代碼如下(為了方便觀察已經改過了,不是解題的代碼)

import sys
x=1
y=100000000
k=100000000
a=k*y+k-1
ans=a/1
print(sys.maxsize)
print(int(a))
print(int(ans))

結果如下:

9223372036854775807
10000000099999999
10000000100000000

輸出的第一行是int的最大值,是為了驗證異常不是由於溢出導致的。

看到第二個輸出,一個算是比較大的數字,第三個輸出應當是其除以1的結果。

用小學生的腦子想一想,任意一個數字除以1結果應當不變吧。

但輸出告訴我們,我不僅變,我還給你剛好+1。

但如果在這里使用整除的話,第二和第三個結果是一致的。

那么問題大約出在python的浮點數除法的算法上了。

如果將除數改為2,可以看到第三個輸出變為

5000000050000000

也就是說,在除法過程中依然出現了+1現象。

如果減小量級呢?

import sys
x=1
y=100000000
k=100000000
a=k+k-1
ans=a/1print(sys.maxsize)
print(int(a))
print(int(ans))

結果如下:

9223372036854775807
199999999
199999999

可以看到,+1現象消失了。

那么推測,+1現象的成因是在浮點運算中為了方便較大數字運算而引入的一個一般情況下可以忽略的填補量。

那么引入這個+1的臨界范圍是什么?

使用while循環,粗略地探究一下:

import sys
x=1
y=100000000
k=100000000
a=k+k-1
ans=a/1;
while a==ans:
    print(int(a))
    a*=10
    ans=a/1print(sys.maxsize)
print(int(a))
print(int(ans))

結果是:

199999999
1999999990
19999999900
199999999000
1999999990000
19999999900000
199999999000000
1999999990000000
19999999900000000
199999999000000000
1999999990000000000
9223372036854775807
19999999900000000000
19999999900000002048

不對勁啊,為什么是在比int范圍還有大的時候才跳出循環,明明之前產生偏差的數值比范圍要小。

猜測,這個偏差的產生條件不只是數字的位數,還有其他的條件

觀察最開始的那個數據,以及1的特殊性,猜測這個+1的偏差可能和數據的末尾9的個數有關

那么選取一個較小的9結尾的數字開始循環

import sys
a=199999
ans=a/1
while a==ans:
print(a)
a=a*10+9
ans=a/1
print(sys.maxsize)
print(int(a))
print(int(ans))

結果是:

199999
1999999
19999999
199999999
1999999999
19999999999
199999999999
1999999999999
19999999999999
199999999999999
1999999999999999
9223372036854775807
19999999999999999
20000000000000000

可以看到,位數與最初那個有偏差數據一樣。

實驗到此結束,暫時的結論是,在被除數大到一定程度(暫定17位)且末尾有一定數量9時,在除法運算中會進行一個+1

的填補以方便運算。

至於這個算法具體的優化過程不得而知,想來與現在的結論應該是大相徑庭吧,只能留待日后有機會再研究了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM