看了圖,我第一感覺就是數(shù)據(jù)溢出了。 數(shù)據(jù)超出能表示的最大值,就會出現(xiàn)奇奇怪怪的結果。
然后,他繼續(xù)發(fā)了張圖,內(nèi)容是 print(100000*208378),就是直接打印上圖的 E[0]*G[0],結果是 20837800000,這是個正確的結果。
所以新的問題是:如果說上圖的數(shù)據(jù)溢出了,為何直接相乘的數(shù)卻沒有溢出?
由于我一直忽視數(shù)據(jù)的表示規(guī)則(整型的上限是多少?),而且對 Numpy 了解不多,還錯看了圖中結果,誤以為每一個數(shù)據(jù)都是錯誤的,所以就解答不出來。
最后,經(jīng)過學習群里的一番討論,我才終于明白是怎么回事,所以本文把相關知識點做個梳理。
-
Python 3 中整數(shù)的上限是多少? Python 2 呢?
-
Numpy 中整數(shù)的上限是多少? 整數(shù)溢出該怎么辦?
-
一種是短整數(shù),也即常說的整數(shù),用 int 表示,有個內(nèi)置函數(shù) int()。其大小有限,可通過
sys.maxint()
查看(取決于平臺是 32 位還是 64 位) -
一種是長整數(shù),即大小無限的整數(shù),用 long 表示,有個內(nèi)置函數(shù) long()。寫法上是在數(shù)字后面加大寫字母 L 或小寫的 l,如 1000L
當一個整數(shù)超出短整數(shù)范圍時,它會自動采用長整數(shù)表示。舉例,打印
2**100
,結果會在末尾加字母 L 表示它是長整數(shù)。
但是到了 Python 3,情況就不同了:它僅有一種內(nèi)置的整數(shù),表示為 int,形式上是 Python 2 的短整數(shù),但實際上它能表示的范圍無限,行為上更像是長整數(shù)。無論多大的數(shù),結尾都不需要字母 L 來作區(qū)分。
也就是說,Python 3 整合了兩種整數(shù)表示法,用戶不再需要自行區(qū)分,全交給底層按需處理。
理論上,Python 3 中的整數(shù)沒有上限(只要不超出內(nèi)存空間)。這就解釋了前文中直接打印兩數(shù)相乘,為什么結果會正確了。
PEP-237(Unifying Long Integers and Integers)中對這個轉(zhuǎn)變作了說明。它解釋這樣做的目的:
這會給新的 Python 程序員(無論他們是否是編程新手)減少一項上手前要學的功課。
Python 在語言運用層屏蔽了很多瑣碎的活,比如內(nèi)存分配,所以,我們在使用字符串、列表或字典等對象時,根本不用操心。整數(shù)類型的轉(zhuǎn)變,也是出于這樣的便利目的。(壞處是犧牲了一些效率,在此就不談了)
回到前面的第二個話題:Numpy 中整數(shù)的上限是多少?
由于它是 C 語言實現(xiàn),在整數(shù)表示上,用的是 C 語言的規(guī)則,也就是會區(qū)分整數(shù)和長整數(shù)。
有一種方式可查看:
import?numpy?as?np
a?=?np.arange(2)
type(a[0])
#?結果:numpy.int32
也就是說它默認的整數(shù) int 是 32 位,表示范圍在 -2147483648 ~ 2147483647。
對照前文的截圖,里面只有兩組數(shù)字相乘時沒有溢出:100007*4549、100012*13264,其它數(shù)據(jù)組都溢出了,所以出現(xiàn)奇怪的負數(shù)結果。
Numpy 支持的數(shù)據(jù)類型要比 Python 的多,相互間的區(qū)分界限很多樣:

要解決整數(shù)溢出,可通過指定 dtype 的方式:
import?numpy?as?np
q?=?[100000]
w?=?[500000]
#?一個溢出的例子:
a?=?np.array(q)
b?=?np.array(w)
print(a*b)??#?產(chǎn)生溢出,結果是個奇怪的數(shù)值
#?一個解決的例子:
c?=?np.array(q,?dtype='int64')
d?=?np.array(w,?dtype='int64')
print(c*d)?#?沒有溢出:[50000000000]
好了,前面提出的問題就回答完了。
-
Python 3 極大地簡化了整數(shù)的表示,效果可表述為:整數(shù)就只有一種整數(shù)(int),沒有其它類型的整數(shù)(long、int8、int64 之類的)
-
Numpy 中的整數(shù)類型對應于 C 語言的數(shù)據(jù)類型,每種“整數(shù)”有自己的區(qū)間,要解決數(shù)據(jù)溢出問題,需要指定更大的數(shù)據(jù)類型(dtype)
往期文章,推薦閱讀:
為什么要翻譯?值得堅持下去么?
Python 之父的解析器系列之四:可視化 PEG 解析
用 Python 實現(xiàn)簡易 Web 服務器
遇見一只黑貓,她說程序員都是騙子
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
