欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Cpython3.9源碼解析python中的大小整數(shù)

 更新時間:2023年04月21日 10:14:09   作者:菜鳥小超  
這篇文章主要介紹了Cpython3.9源碼解析python中的大小整數(shù),在CPython中,小整數(shù)對象池是一種優(yōu)化機制,用于減少對常用小整數(shù)的內(nèi)存分配和銷毀開銷,需要的朋友可以參考下

小整數(shù)

/* interpreter state */

#define _PY_NSMALLPOSINTS           257
#define _PY_NSMALLNEGINTS           5

這是CPython中定義的兩個常量,它們用于控制解釋器狀態(tài)中的小整數(shù)對象池。在CPython中,小整數(shù)對象池是一種優(yōu)化機制,用于減少對常用小整數(shù)的內(nèi)存分配和銷毀開銷。

_PY_NSMALLPOSINTS定義了正小整數(shù)對象池的大小。在這里,其值設(shè)置為257,表示解釋器將為從0到256(包含0和256)的整數(shù)預(yù)分配對象并緩存。這些整數(shù)在很多場景下會被頻繁使用,所以事先創(chuàng)建并緩存它們可以提高性能。

_PY_NSMALLNEGINTS定義了負小整數(shù)對象池的大小。在這里,其值設(shè)置為5,表示解釋器將為從-1到-5(包含-1和-5)的整數(shù)預(yù)分配對象并緩存。

在Python解釋器啟動時,這些小整數(shù)對象會被創(chuàng)建并放入對象池。當需要這些整數(shù)值時,解釋器會直接從對象池中獲取對應(yīng)的對象,而不是動態(tài)創(chuàng)建新對象。這樣,對于這些小整數(shù)值的操作可以更快地進行,節(jié)省了內(nèi)存分配和銷毀的開銷。

static PyObject *
get_small_int(sdigit ival)
{
    assert(IS_SMALL_INT(ival));
    PyThreadState *tstate = _PyThreadState_GET();
    PyObject *v = (PyObject*)tstate->interp->small_ints[ival + NSMALLNEGINTS];
    Py_INCREF(v);
    return v;
}

typedef int32_t sdigit; /* signed variant of digit */

#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)

這是get_small_int函數(shù)的實現(xiàn),它用于從小整數(shù)對象池中獲取一個指定值的小整數(shù)對象。小整數(shù)對象池包含了一定范圍內(nèi)的整數(shù)對象,主要是為了避免對這些常用的整數(shù)對象進行頻繁的內(nèi)存分配和銷毀。

get_small_int函數(shù)接受一個sdigit類型的參數(shù)ival,表示要獲取的整數(shù)值。在函數(shù)內(nèi)部,首先使用assert(IS_SMALL_INT(ival))確保傳入的整數(shù)值ival在小整數(shù)對象池的范圍內(nèi)。

接下來,函數(shù)獲取當前線程狀態(tài)(PyThreadState)并從其中獲取解釋器狀態(tài)(tstate->interp)。解釋器狀態(tài)包含了小整數(shù)對象池,即small_ints數(shù)組

然后,根據(jù)ival計算出在small_ints數(shù)組中的索引(ival + NSMALLNEGINTS),并將對應(yīng)位置的對象賦值給v。NSMALLNEGINTS是一個宏定義,表示負小整數(shù)的個數(shù)。假設(shè)我們有一個整數(shù)值 ival,我們想要在 small_ints 數(shù)組中查找這個值對應(yīng)的預(yù)分配的小整數(shù)對象。NSMALLNEGINTS 是預(yù)分配的負數(shù)的數(shù)量。在 CPython 中,NSMALLNEGINTS 的值通常為5,表示有5個預(yù)分配的負整數(shù)對象(-1, -2, -3, -4, -5)。

現(xiàn)在,我們將通過計算 ival + NSMALLNEGINTS 來找到 small_ints 數(shù)組中的索引。例如,假設(shè) ival 為3。那么,我們可以計算索引如下:

index = ival + NSMALLNEGINTS
index = 3 + 5
index = 8

這意味著 small_ints 數(shù)組中的第8個元素(從0開始計數(shù))是我們要查找的整數(shù)對象。在這個例子中,我們將找到預(yù)分配的小整數(shù)對象3,并將其引用計數(shù)加1,然后返回這個對象。

接下來,通過調(diào)用Py_INCREF(v)增加v的引用計數(shù),以防止對象在其引用計數(shù)變?yōu)?時被錯誤地回收。

最后,返回指向小整數(shù)對象的指針v

總之,get_small_int函數(shù)的作用是從小整數(shù)對象池中獲取一個指定值的小整數(shù)對象,并增加其引用計數(shù),然后返回該對象。這樣可以提高對常用小整數(shù)的操作性能。

大整數(shù)

/* Long integer representation.
   The absolute value of a number is equal to
        SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
   Negative numbers are represented with ob_size < 0;
   zero is represented by ob_size == 0.
   In a normalized number, ob_digit[abs(ob_size)-1] (the most significant
   digit) is never zero.  Also, in all cases, for all valid i,
        0 <= ob_digit[i] <= MASK.
   The allocation function takes care of allocating extra memory
   so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available.

   CAUTION:  Generic code manipulating subtypes of PyVarObject has to
   aware that ints abuse  ob_size's sign bit.
*/

這是CPython源碼中關(guān)于長整數(shù)表示的一段注釋。它解釋了PyLongObject如何表示大整數(shù)的絕對值和符號。讓我們逐行分析這個注釋:

1.首先,注釋指出大整數(shù)的絕對值等于:

SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)

ob_digit表示長整數(shù)的每個“數(shù)字”,SHIFT是每個“數(shù)字”的位數(shù),通常為30或15。ob_size表示長整數(shù)的符號和長度,它的絕對值表示長整數(shù)的長度,即“數(shù)字”的個數(shù)。

2.對于負數(shù),ob_size小于0。對于0,ob_size等于0。

3.在規(guī)范化的數(shù)中,最高有效位(即最高“數(shù)字”)永遠不會為零。此外,在所有情況下,對于所有有效的i,ob_digit[i]的取值范圍在0到MASK之間。MASK的值通常為(1 << PyLong_SHIFT) - 1,即2**PyLong_SHIFT - 1。

4.注釋還提到分配函數(shù)負責分配額外的內(nèi)存,以確保ob_digit[0]ob_digit[abs(ob_size)-1]實際上是可用的。

5.最后,注釋中的“警告”部分提醒開發(fā)者,操縱PyVarObject子類型的通用代碼需要注意整數(shù)會濫用ob_size的符號位。這是因為ob_size的符號位同時表示整數(shù)的長度和符號,而通常情況下ob_size僅用于表示長度。

額外解釋

ob_digit 是一個表示大整數(shù)中每個 “數(shù)字” 的數(shù)組,它是一個整數(shù)數(shù)組,用于表示長整數(shù)對象(PyLongObject)中的整數(shù)值。每個 “數(shù)字” 都有一個固定的位數(shù),由 PyLong_SHIFT 定義(通常為 30 或 15)。例如,假設(shè)我們有一個長整數(shù)對象,其值為 12345678901234567890。

在這個例子中,假設(shè) PyLong_SHIFT 為 30,這意味著每個 “數(shù)字” 可以表示 2^30 = 1073741824 個不同的值。為了將這個大整數(shù)表示為 ob_digit 數(shù)組,我們需要將整數(shù)拆分為基于 2^30 的 “數(shù)字”。在這種情況下,我們可以將整數(shù)表示為:

12345678901234567890 = 4 * 2^(30*2) + 726238597 * 2^(30*1) + 1026062870 * 2^(30*0)

所以,ob_digit 數(shù)組將包含以下元素:

ob_digit[0] = 1026062870
ob_digit[1] = 726238597
ob_digit[2] = 4

在實際的 CPython 源碼中,PyLongObject 的定義如下:

typedef struct {
    PyObject_VAR_HEAD
    digit ob_digit[1];
} PyLongObject;

在這里,ob_digit 是一個長度為1的數(shù)組,但實際上,它是一個可變長度數(shù)組,根據(jù)所需的 “數(shù)字” 數(shù)量動態(tài)分配。要注意的是,當一個 PyLongObject 被創(chuàng)建時,會根據(jù)整數(shù)值的大小動態(tài)分配適當數(shù)量的空間來存儲 ob_digit 數(shù)組。

總之,ob_digit 是一個整數(shù)數(shù)組,用于表示長整數(shù)對象中的大整數(shù)值。每個數(shù)組元素都是一個 “數(shù)字”,具有固定的位數(shù)。這種表示方法使得 CPython 能夠有效地存儲和處理大整數(shù)。

到此這篇關(guān)于Cpython3.9源碼解析python中的大小整數(shù)的文章就介紹到這了,更多相關(guān)Cpython3.9源碼解析大小整數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論