@@ -109,6 +109,107 @@ PyTypeObject PyLong_Type = {
109109};
110110```
111111
112+ ## 创建整数对象
113+
114+ 从 PyLong_Type 可以看出,创建一个整数对象的入口函数为 long_new
115+
116+ ` 源文件: ` [ Objects/clinic/longobject.c.h] ( https://github.com/python/cpython/blob/v3.7.0/Objects/clinic/longobject.c.h#L0 )
117+
118+ ``` c
119+ // Objects/clinic/longobject.c.h
120+ /* [clinic input]
121+ preserve
122+ [clinic start generated code]*/
123+
124+ static PyObject *
125+ long_new_impl (PyTypeObject * type, PyObject * x, PyObject * obase);
126+
127+ static PyObject *
128+ long_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
129+ {
130+ PyObject * return_value = NULL;
131+ static const char * const _ keywords[ ] = {"", "base", NULL};
132+ static _ PyArg_Parser _ parser = {"|OO: int ", _ keywords, 0};
133+ PyObject * x = NULL;
134+ PyObject * obase = NULL;
135+
136+ if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
137+ &x, &obase)) {
138+ goto exit;
139+ }
140+ return_value = long_new_impl(type, x, obase);
141+
142+ exit:
143+ return return_value;
144+ }
145+ ```
146+
147+ 具体实现在 long_new_impl `源文件:`[Objects/longobject.c](https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L4785)
148+
149+ ```c
150+ // Objects/longobject.c
151+
152+ /*[clinic input]
153+ @classmethod
154+ int.__new__ as long_new
155+ x: object(c_default="NULL") = 0
156+ /
157+ base as obase: object(c_default="NULL") = 10
158+ [clinic start generated code]*/
159+
160+ static PyObject *
161+ long_new_impl(PyTypeObject *type, PyObject *x, PyObject *obase)
162+ /*[clinic end generated code: output=e47cfe777ab0f24c input=81c98f418af9eb6f]*/
163+ {
164+ Py_ssize_t base;
165+
166+ if (type != &PyLong_Type)
167+ return long_subtype_new(type, x, obase); /* Wimp out */
168+ if (x == NULL) {
169+ if (obase != NULL) {
170+ PyErr_SetString(PyExc_TypeError,
171+ "int() missing string argument");
172+ return NULL;
173+ }
174+ return PyLong_FromLong(0L);
175+ }
176+ if (obase == NULL)
177+ return PyNumber_Long(x);
178+
179+ base = PyNumber_AsSsize_t(obase, NULL);
180+ if (base == -1 && PyErr_Occurred())
181+ return NULL;
182+ if ((base != 0 && base < 2) || base > 36) {
183+ PyErr_SetString(PyExc_ValueError,
184+ "int() base must be >= 2 and <= 36, or 0");
185+ return NULL;
186+ }
187+
188+ if (PyUnicode_Check(x))
189+ return PyLong_FromUnicodeObject(x, (int)base);
190+ else if (PyByteArray_Check(x) || PyBytes_Check(x)) {
191+ char *string;
192+ if (PyByteArray_Check(x))
193+ string = PyByteArray_AS_STRING(x);
194+ else
195+ string = PyBytes_AS_STRING(x);
196+ return _PyLong_FromBytes(string, Py_SIZE(x), (int)base);
197+ }
198+ else {
199+ PyErr_SetString(PyExc_TypeError,
200+ "int() can't convert non-string with explicit base");
201+ return NULL;
202+ }
203+ }
204+ ```
205+
206+ 从 long_new_impl 函数可以看出有如下几种情况
207+
208+ - x == NULL 且 obase != NULL 调用 PyLong_FromLong
209+ - obase 为NULL 调用 PyNumber_Long
210+ - x 和 obase 都不为 NULL
211+ - PyUnicode 调用PyLong_FromUnicodeObject,最终调用PyLong_FromString
212+ - PyByteArray/PyBytes 调用_PyLong_FromBytes,最终调用PyLong_FromString
112213
113214## 小整数对象
114215
@@ -293,7 +394,7 @@ print(num)
293394
294395## 整数对象的数值操作
295396
296- 可以看到整数对象的数值操作较多,由于篇幅限制无法一一分析,这里只分析整数的部分方法
397+ 可以看到整数对象的数值操作较多,由于篇幅限制无法一一分析,这里只分析整数的部分操作
297398
298399` 源文件: ` [ Objects/longobject.c] ( https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L5341 )
299400
@@ -340,13 +441,54 @@ static PyNumberMethods long_as_number = {
340441
341442### 整数相加
342443
343- ` 源文件: ` [ Objects/longobject.c] ( https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L2990 )
444+ ` 源文件: ` [ Objects/longobject.c] ( https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L3081 )
344445
345446``` c
346447// Objects/longobject.c
347448
348- /* Add the absolute values of two integers. */
449+ static PyObject *
450+ long_add (PyLongObject * a, PyLongObject * b)
451+ {
452+ PyLongObject * z;
453+
454+ CHECK_BINOP(a, b);
455+
456+ if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
457+ return PyLong_FromLong(MEDIUM_VALUE(a) + MEDIUM_VALUE(b));
458+ }
459+ if (Py_SIZE(a) < 0) {
460+ if (Py_SIZE(b) < 0) {
461+ z = x_add(a, b);
462+ if (z != NULL) {
463+ /* x_add received at least one multiple-digit int,
464+ and thus z must be a multiple-digit int.
465+ That also means z is not an element of
466+ small_ints, so negating it in-place is safe. */
467+ assert(Py_REFCNT(z) == 1);
468+ Py_SIZE(z) = -(Py_SIZE(z));
469+ }
470+ }
471+ else
472+ z = x_sub(b, a);
473+ }
474+ else {
475+ if (Py_SIZE(b) < 0)
476+ z = x_sub(a, b);
477+ else
478+ z = x_add(a, b);
479+ }
480+ return (PyObject *)z;
481+ }
482+ ```
483+
484+ 可以看到整数的加法运算函数long_add根据 a、b的ob_size 又细分为两个函数 (x_add 和 x_sub) 做处理
485+
486+ `源文件:`[Objects/longobject.c](https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L2991)
487+
488+ ```c
489+ // Objects/longobject.c
349490
491+ /* Add the absolute values of two integers. */
350492static PyLongObject *
351493x_add(PyLongObject *a, PyLongObject *b)
352494{
@@ -379,6 +521,17 @@ x_add(PyLongObject *a, PyLongObject *b)
379521 z->ob_digit[i] = carry;
380522 return long_normalize(z);
381523}
524+ ```
525+
526+ 加法运算函数 x_add 从 ob_digit 数组的低位开始依次按位相加,carry做进位处理,然后处理a对象的高位数字,最后使用 long_normalize 函数调整 ob_size,确保ob_digit[ abs(ob_size)-1] 不为零,这与普通四则运算的加法运算相同,只不过进位单元不同而已
527+
528+ ![ longobject x_add] ( longobject_x_add.png )
529+
530+
531+ ` 源文件: ` [ Objects/longobject.c] ( https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L3025 )
532+
533+ ``` c
534+ // Objects/longobject.c
382535
383536/* Subtract the absolute values of two integers. */
384537
@@ -423,7 +576,7 @@ x_sub(PyLongObject *a, PyLongObject *b)
423576 borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
424577 z->ob_digit[i] = borrow & PyLong_MASK;
425578 borrow >>= PyLong_SHIFT;
426- borrow &= 1; /* Keep only one sign bit 只保留一位符号位 */
579+ borrow &= 1; /* Keep only one sign bit */
427580 }
428581 for (; i < size_a; ++i) {
429582 borrow = a->ob_digit[i] - borrow;
@@ -437,50 +590,10 @@ x_sub(PyLongObject *a, PyLongObject *b)
437590 }
438591 return long_normalize(z);
439592}
440-
441- static PyObject *
442- long_add(PyLongObject * a, PyLongObject * b)
443- {
444- PyLongObject * z;
445-
446- CHECK_BINOP(a, b);
447-
448- if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
449- return PyLong_FromLong(MEDIUM_VALUE(a) + MEDIUM_VALUE(b));
450- }
451- if (Py_SIZE(a) < 0) {
452- if (Py_SIZE(b) < 0) {
453- z = x_add(a, b);
454- if (z != NULL) {
455- /* x_add received at least one multiple-digit int,
456- and thus z must be a multiple-digit int.
457- That also means z is not an element of
458- small_ints, so negating it in-place is safe. */
459- assert(Py_REFCNT(z) == 1);
460- Py_SIZE(z) = -(Py_SIZE(z));
461- }
462- }
463- else
464- z = x_sub(b, a);
465- }
466- else {
467- if (Py_SIZE(b) < 0)
468- z = x_sub(a, b);
469- else
470- z = x_add(a, b);
471- }
472- return (PyObject *)z;
473- }
474593```
475594
476- 可以看到整数的加法运算函数long_add根据 a、b的ob_size 又细分为两个函数做处理 x_add 和 x_sub
477-
478- 加法运算函数 x_add 从 ob_digit 数组的低位开始依次按位相加,carry做进位处理,
479- 然后做处理a对象的高位数字,最后使用 long_normalize 函数调整 ob_size,确保ob_digit[abs(ob_size)-1]不为零,其过程大致如下图
480-
481- 
482-
483- 减法运算函数 x_sub 的过程大致如下图
595+ 与普通四则运算减法相同,数不够大则向高一位借位,
596+ 减法运算函数 x_sub 的示例图如下,注:PyLong_SHIFT为30
484597
485598
486599
@@ -514,7 +627,11 @@ long_mul(PyLongObject *a, PyLongObject *b)
514627}
515628```
516629
517- k_mul函数 [ 源文件] (
630+ k_mul函数是一种快速乘法 [ 源文件] (
518631https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L3268 )
519632
520- ` k_mul ` 函数是一种快速乘法[ Karatsuba算法] ( https://www.wikiwand.com/zh-hans/Karatsuba算法 ) 的实现
633+ > Karatsuba的算法主要是用于两个大数的乘法,极大提高了运算效率,相较于普通乘法降低了复杂度,并在其中运用了递归的思想。
634+ > 基本的原理和做法是将位数很多的两个大数x和y分成位数较少的数,每个数都是原来x和y位数的一半。
635+ > 这样处理之后,简化为做三次乘法,并附带少量的加法操作和移位操作。
636+
637+ 具体可以看wiki [ Karatsuba算法] ( https://www.wikiwand.com/zh-hans/Karatsuba算法 ) 的实现
0 commit comments