【Python源碼探析】Python 整數(shù)數(shù)據(jù)類型的實現(xiàn)

聲明:本文僅限于簡書發(fā)布,其他第三方網(wǎng)站均為盜版靶草,原文地址: Python 整數(shù)數(shù)據(jù)類型的實現(xiàn)

接著之前的 《Python 對象模型》繼續(xù)看看 Python 的源代碼岳遥,之前說了派继,Python 的一切數(shù)據(jù)都是對象,甚至于不是數(shù)據(jù)都是對象绅络,例如函數(shù)啊寻行,類啊這些這些對象简卧。其實构罗,在 Python 的實現(xiàn)中遂唧,套路都差不多,無非是關注這些對象是怎么創(chuàng)建的召边,然后內(nèi)部的數(shù)據(jù)結構是怎么編排的,有什么優(yōu)化策略這些片挂,所以,我就準備不多看滋将,就看看整數(shù)的實現(xiàn)症昏。

對于 Python 整數(shù),我開始學的時候有個很感興趣的點就是 Python 的整數(shù)居然是沒有溢出的掘宪,例如這些代碼你就可以看出來了:

有意思吧攘烛,一個整數(shù)左移了 100 位都沒溢出,我想你肯定不會說內(nèi)部是用一個 128 位的數(shù)據(jù)類型來實現(xiàn)的鼠次,好像現(xiàn)在 C 語言中也還沒這個類型吧芋齿?

整數(shù)的內(nèi)部結構

之前一篇文章說過啦,整數(shù)的數(shù)據(jù)結構是 PyLongObject赦役,沒說也至少提到過栅炒,所以我就直接看這個數(shù)據(jù)結構好啦:

很簡單赢赊,可以看到數(shù)據(jù)是保存到了一個指針(這里定義的是一個元素為1的數(shù)組释移,似乎是 C 語言里面的慣用套路)里頭秀鞭,然后這個數(shù)據(jù)長度是放在 PyOBject_VAR_HEAD 里面的啦扛禽,后面會看到關于他的操作。

新建和刪除一個整數(shù)

新建和刪除一個整數(shù)在 Python 里面是有一點點優(yōu)化的豆巨,類似于 Java掐场,對于小整數(shù)贩猎,Python 會在啟動的時候先創(chuàng)建好萍膛,后面要用的時候就不用創(chuàng)建了蝗罗,直接增加引用計數(shù)即可,放在你也改變不了一個整數(shù)的值(不可變對象)串塑,至于小整數(shù)的定義,看代碼中的這個值:


這里也就是將 [-5, 257) 范圍內(nèi)的整數(shù)都定義為小整數(shù)打瘪。所以創(chuàng)建的時候闺骚,如果數(shù)字是這個返回就直接返回已經(jīng)創(chuàng)建好的對象了:

這是定義的一個檢查小整數(shù)的宏屋匕,在創(chuàng)建整數(shù)對象的時候都會先檢驗一遍,然后不是小整數(shù)才會做其他整數(shù)的操作:


這里 Line 44 就是檢查并且返回小整數(shù)的宏进泼,實現(xiàn)就很簡單了纤虽,再來看看其他整數(shù)是怎么操作的逼纸,我們前面看到了,整數(shù)都是被拆到一個個 digit 里面的杰刽,digit 的大小不確定,可能是 15 bit 或者 30 bit滓鸠。所以這里第一步是先確定需要多少個 digit第喳,Line49 就是在計算,然后 Line 52 就創(chuàng)建對應長度的對象悠抹,因為我們說了,digit 是一個數(shù)組啤挎,需要調(diào)節(jié)它的長度卵凑。然后 Line 58 就是拆分保存數(shù)據(jù)了。

這里還有一點沒高亮的是 Line 55氛谜,這里將這個整數(shù)的正負保存在 ob_size 這個字段值漫,而不是保存在 digit 里面,也就是說 digit 里面保存的是數(shù)字的絕對值杨何,這樣有什么好處危虱?操作方便啊,加減乘除都不需要擔心符號的問題埃跷,而且拆分也是大膽得拆,不需要考慮符號問題垃帅。

整數(shù)的加減乘除

整數(shù)這么創(chuàng)建的話剪勿,加減我們就比較簡單得可以猜到了,就是直接加和直接減少酱固,來點簡單的代碼吧:

可以看到运悲,就兩個循環(huán)髓窜,一個個 digit 得加,唯一需要注意的就是 長度 和 進位 的問題寄纵。加減是簡單,但是乘除就復雜了定踱,乘法的我還能看得明白一些恃鞋,除法的我直接就放棄了,很復雜畅哑,引用注釋的一段話:

/* We follow Knuth [The Art of Computer Programming, Vol. 2 (3rd
   edn.), section 4.3.1, Algorithm D], except that we don't explicitly
   handle the special case when the initial estimate q for a quotient
   digit is >= PyLong_BASE: the max value for q is PyLong_BASE+1, and
   that won't overflow a digit. */

那就記錄點我看懂了的乘法吧水由,因為它將整數(shù)拆成一個個 digit,所以乘法也就是一個個 digit 來乘泥张,我們可以想象一下小學的時候學的乘法:

這是 10進制的嘛媚创,然后我們可以將一個 digit 當成一位彤恶,也是可以實現(xiàn)的,但是声离,就是更復雜了一些,為了減少一些乘法操作焕议,Python 進行了一點點的優(yōu)化:

  /* (ah*X+al)(bh*X+bl) = ah*bh*X*X + (ah*bl + al*bh)*X + al*bl
 * Let k = (ah+al)*(bh+bl) = ah*bl + al*bh  + ah*bh + al*bl
 * Then the original product is
 *     ah*bh*X*X + (k - ah*bh - al*bl)*X + al*bl
 * By picking X to be a power of 2, "*X" is just shifting, and it's
 * been reduced to 3 multiplies on numbers half the size.
 */

這里的目的就是將大的整數(shù)的乘法轉化成小一半的整數(shù)的乘法盅安,從而減少真正乘法的規(guī)模和次數(shù)世囊,同時,這里的 X 因為是 2 的倍數(shù)株憾,所以直接移位就可以了,效率不能更高墙歪,所以真正的乘法就變少了。

Reference

  1. Why do some structures end with an array of size 1?
  2. Multiplication algorithm
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末靠胜,一起剝皮案震驚了整個濱河市浪漠,隨后出現(xiàn)的幾起案子霎褐,更是在濱河造成了極大的恐慌,老刑警劉巖冻璃,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱饿,死亡現(xiàn)場離奇詭異,居然都是意外死亡失驶,警方通過查閱死者的電腦和手機枣购,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門棉圈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人分瘾,你說我怎么就攤上這事“谆辏” “怎么了上岗?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵肴掷,是天一觀的道長背传。 經(jīng)常有香客問我台夺,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任买窟,我火速辦了婚禮薯定,結果婚禮上,老公的妹妹穿的比我還像新娘亏推。我一直安慰自己年堆,他們只是感情好,可當我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布芽狗。 她就那樣靜靜地躺著痒蓬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪顾复。 梳的紋絲不亂的頭發(fā)上鲁捏,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天给梅,我揣著相機與錄音,去河邊找鬼破喻。 笑死,一個胖子當著我的面吹牛婴噩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播几莽,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼章蚣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了矾策?” 一聲冷哼從身側響起峭沦,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蓬豁,沒想到半個月后菇肃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡驶忌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年付魔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片飞蹂。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡几苍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出陈哑,到底是詐尸還是另有隱情妻坝,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布惊窖,位于F島的核電站刽宪,受9級特大地震影響,放射性物質發(fā)生泄漏界酒。R本人自食惡果不足惜圣拄,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毁欣。 院中可真熱鬧岳掐,春花似錦、人聲如沸饭耳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寞肖。三九已至纲酗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間新蟆,已是汗流浹背觅赊。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留栅葡,地道東北人茉兰。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓尤泽,卻偏偏與公主長得像欣簇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坯约,可洞房花燭夜當晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 8086匯編 本筆記是筆者觀看小甲魚老師(魚C論壇)《零基礎入門學習匯編語言》系列視頻的筆記堕花,在此感謝他和像他一樣...
    Gibbs基閱讀 37,192評論 8 114
  • 第一章數(shù)和數(shù)的運算 一概念 (一)整數(shù) 1整數(shù)的意義 自然數(shù)和0都是整數(shù)文狱。 2自然數(shù) 我們在數(shù)物體的時候,用來表示...
    meychang閱讀 2,601評論 0 5
  • http://python.jobbole.com/85231/ 關于專業(yè)技能寫完項目接著寫寫一名3年工作經(jīng)驗的J...
    燕京博士閱讀 7,575評論 1 118
  • 前言 Python的創(chuàng)始人為Guido van Rossum缘挽。1989年圣誕節(jié)期間瞄崇,在阿姆斯特丹,Guido為了打...
    依依玖玥閱讀 3,568評論 6 37
  • 定點小數(shù)運算 來自:http://www.eepw.com.cn/article/17893.htm 在DSP世界...
    郝宇峰閱讀 9,103評論 0 2