python 将数组转化8位整数_int对象,永不溢出的整数
點擊上方藍色小字 “小菜學編程”?,關注我們?
整數溢出
開始介紹 int?對象前,先考考大家:下面這個?C?程序( test.c?)運行后輸出什么?是 1000000000000?(一萬億)嗎?
#include?int?main(int?argc,?char?*argv[]){
????int?value?=?1000000;
????printf("%d\n",?value?*?value);
????return?0;
}
可能有不少人覺得這沒啥好問的,一百萬乘以一百萬不就是一萬億嗎?但現實卻不是如此。
在計算機中,由于變量類型存儲空間固定,它能表示的數值范圍也是有限的。以 int?為例,該類型長度為 32?位,能表示的整數范圍為 -2147483648?至?2147483647?。一萬億顯然超出該范圍,換句話講程序發生了 整數溢出?。因此,運行 test.c?,程序這樣輸出也就不奇怪了:
$?gcc?-o?test?test.c$?./test
-727379968
不僅是 C?語言,很多編程語言都存在整數溢出的問題,數據庫中的整數類型也是。由于整數溢出現象的存在,程序員需要結合業務場景,謹慎選擇數據類型。一旦選擇不慎或者代碼考慮不周,便會導致嚴重 BUG?。
int 對象的行為
與其他語言相比,?Python?中的整數永遠不會有溢出的現象。一百萬乘以一百萬, Python?可以輕易算出來:
>>>?1000000?*?10000001000000000000
Pyhton?甚至可以計算十的一百次方,這在其他語言是不可想象的:
>>>?10?**?10010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
計算結果如此龐大,就算用 64?位整數,也難以表示。但?Python?中的整數對象卻可以輕松應付,完全不需要任何特殊處理。為什么?Python?整數有這樣的魔力呢?讓我們深入整數對象源碼,撥開心中的迷霧。
在源碼中,我們將領略到?C?語言 實現大整數的藝術?。也許你曾經被面試官要求用 C/C++?實現大整數,卻因為考慮不周而不幸敗北。不要緊,掌握 Python?整數的設計秘密后,實現大整數對你來說將是易如反掌。
int 對象的設計
int?對象在 Include/longobject.h?頭文件中定義:
typedef?struct?_longobject?PyLongObject;?/*?Revealed?in?longintrepr.h?*/我們順著注釋找到了 Include/longintrepr.h?,實現 int?對象的結構體真正藏身之處:
struct?_longobject?{????PyObject_VAR_HEAD
????digit?ob_digit[1];
};
這個結構我們并不陌生,說明 int?對象是一個變長對象。除了變長對象都具有的公共頭部,還有一個 digit?數組,整數值應該就存儲在這個數組里面。digit?又是什么呢?同樣在 Include/longintrepr.h?頭文件,我們找到它的定義:
#if?PYLONG_BITS_IN_DIGIT?==?30typedef?uint32_t?digit;
//?...
#elif?PYLONG_BITS_IN_DIGIT?==?15
typedef?unsigned?short?digit;
//?...
#endif
看上去 digit?就是一個 C?語言整數,至此我們知曉?int?對象是通過整數數組來實現大整數的。一個 C?整數類型不夠就兩個嘛,兩個不夠那就 n?個!至于整數數組用什么整數類型來實現, Python?提供了兩個版本,一個是 32?位的 uint32_t ,一個是 16?位的 unsigned short?,編譯?Python?解析器時可以通過宏定義指定選用的版本。
這主要是出于內存方面的考量:對于范圍不大的整數,用?16?位整數表示即可,用 32?位就有點浪費。本人卻覺得由于整數對象公共頭部已經占了 24?字節,省這?2?個字節其實意義不大。
| 16位整數數組 | 32位整數數組 | |
| 1 | 24 + 2 * 1 = 26 | 24 + 4 * 1 = 28 |
| 1000000 | 24 + 2 * 2 = 28 | 24 + 4 * 1 = 28 |
| 10000000000 | 24 + 2 * 3 = 30 | 24 + 4 * 2 = 32 |
由此可見,選用 16?位整數數組時, int?對象內存增長的粒度更小,有些情況下可以節省 2?個字節。但是這 2?字節相比 24?字節的變長對象公共頭部顯得微不足道,因此 Python?默認選用 32?位整數數組也就不奇怪了。
如上圖,對于比較大的整數, Python 將其拆成若干部分,保存在 ob_digit 數組中。然而我們注意到在結構體定義中, ob_digit 數組長度卻固定為 1 ,這是為什么呢?由于 C 語言中數組長度不是類型信息,我們可以根據實際需要為 ob_digit 數組分配足夠的內存,并將其當成長度為 n 的數組操作。這也是 C 語言中一個常用的編程技巧。
通過上面的學習,我們知道 int 對象是通過整數數組來實現大整數的。那么,大整數實現的原理又是如何的呢?
點擊 “
???原創不易,求贊,求在看
總結
以上是生活随笔為你收集整理的python 将数组转化8位整数_int对象,永不溢出的整数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ3040:最短路——题解
- 下一篇: redis的密码验证,及哨兵的相关配置