Hướng dẫn python 128-bit int - python 128-bit int

Nếu bạn thực sự muốn làm việc với các số nguyên 128 bit thì bạn không cần phải lo lắng về sự liên kết. Không có kiến ​​trúc hiện tại, không có máy nào mà Python chạy, hỗ trợ số học nguyên bản địa 128 bit. Vì vậy, không có máy nào yêu cầu hoặc được hưởng lợi từ việc có các số nguyên 128 bit được căn chỉnh 16 byte. Chỉ cần sử dụng cấu trúc do người dùng xác định đó và bạn sẽ ổn.

Nếu những gì bạn thực sự yêu cầu là hỗ trợ cho các loại vectơ 128 bit thì có lẽ bạn sẽ cần phải căn chỉnh chúng. Đó là, bạn cần chúng được căn chỉnh nếu bạn đang tạo chúng theo mã Python và chuyển chúng bằng cách tham chiếu đến mã C/C ++. Bạn không thể vượt qua chúng một cách đáng tin cậy bởi giá trị Không có cách nào để có được CTYPE để căn chỉnh chúng đúng cách trên ngăn xếp (nếu điều đó được yêu cầu bởi kiến ​​trúc ABI). Các vectơ được truyền từ C/C ++ sang Python có lẽ đã được căn chỉnh đúng cách. Vì vậy, nếu bạn có thể sắp xếp nó để tất cả các vectơ của bạn được phân bổ trong mã C/C ++, bạn cũng sẽ ổn với cấu trúc do người dùng của bạn xác định.

Giả sử rằng bạn thực sự cần phải tạo các vectơ liên kết trong mã Python sau đó tôi đã bao gồm mã cho các mảng CTYPE được căn chỉnh. Tôi cũng có mã để sắp xếp các loại CTYPES khác mà tôi chưa đưa vào kích thước mã hợp lý. Mảng là đủ cho hầu hết các mục đích. Những mảng phù hợp này có một vài hạn chế. Chúng sẽ không được căn chỉnh đúng cách nếu bạn chuyển chúng theo giá trị cho các chức năng C/C ++ hoặc nếu bạn đưa chúng làm thành viên trong một cấu trúc hoặc liên minh. Bạn có thể tạo các mảng được căn chỉnh của các mảng được căn chỉnh bằng toán tử ____10.

Sử dụng

class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
1 để tạo các loại mảng được căn chỉnh mới. Sử dụng
class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
2 để tạo phiên bản căn chỉnh của loại mảng đã có.

import ctypes

ArrayType = type(ctypes.Array)

class _aligned_array_type(ArrayType):
    def __mul__(self, length):
        return aligned_array_type(self._type_ * self._length_,
                      length, self._alignment_)

    def __init__(self, name, bases, d):
        self._alignment_ = max(getattr(self, "_alignment_", 1), 
                       ctypes.alignment(self))

def _aligned__new__(cls):
    a = cls._baseclass_.__new__(cls)
    align = cls._alignment_
    if ctypes.addressof(a) % align == 0:
        return a
    cls._baseclass_.__init__(a) # dunno if necessary
    ctypes.resize(a, ctypes.sizeof(a) + align - 1)
    addr = ctypes.addressof(a)
    aligned = (addr + align - 1) // align * align
    return cls.from_buffer(a, aligned - addr)

class aligned_base(object):
    @classmethod
    def from_address(cls, addr):
        if addr % cls._alignment_ != 0:
            raise ValueError, ("address must be %d byte aligned"
                       % cls._alignment_)
        return cls._baseclass_.from_address(cls, addr)

    @classmethod
    def from_param(cls, addr):
        raise ValueError, ("%s objects may not be passed by value"
                   % cls.__name__)

class aligned_array(ctypes.Array, aligned_base):
    _baseclass_ = ctypes.Array
    _type_ = ctypes.c_byte
    _length_ = 1
    __new__ = _aligned__new__

_aligned_type_cache = {}

def aligned_array_type(typ, length, alignment = None):
    """Create a ctypes array type with an alignment greater than natural"""

    natural = ctypes.alignment(typ)
    if alignment == None:
        alignment = typ._alignment_
    else:
        alignment = max(alignment, getattr(typ, "_alignment_", 1))

    if natural % alignment == 0:
        return typ * length
    eltsize = ctypes.sizeof(typ)
    eltalign = getattr(typ, "_alignment_", 1)
    if eltsize % eltalign != 0:
        raise TypeError("type %s can't have element alignment %d"
                " in an array" % (typ.__name__, alignment))
    key = (_aligned_array_type, (typ, length), alignment)
    ret = _aligned_type_cache.get(key)
    if ret == None:
        name = "%s_array_%d_aligned_%d" % (typ.__name__, length,
                           alignment)
        d = {"_type_": typ,
             "_length_": length,
             "_alignment_": alignment}
        ret = _aligned_array_type(name, (aligned_array,), d)
        _aligned_type_cache[key] = ret
    return ret

def aligned_type(typ, alignment):
    """Create a ctypes type with an alignment greater than natural"""

    if ctypes.alignment(typ) % alignment == 0:
        return typ
    if issubclass(typ, ctypes.Array):
        return aligned_array_type(typ._type_, typ._length_,
                      alignment)
    else:
        raise TypeError("unsupported type %s" % typ)

Tôi đã xem xét đánh giá tay nhanh trong Python. Nó xảy ra với tôi rằng một cách để tăng tốc quá trình sẽ là đại diện cho tất cả các mặt và phù hợp với các số nguyên tố và nhân chúng lại với nhau để đại diện cho bàn tay. Để Whit:

Nội phân chính

  • Đại diện và định nghĩa
  • Giải mã ob_digit
  • Giải mã ob_size
  • Cách pythonic
  • Ví dụ: 1152921504606846976
  • Hoạt động trên các số nguyên siêu dài
  • Phép trừ
  • Phép nhân
  • Bộ phận và các hoạt động khác
  • Tối ưu hóa các số nguyên thường được sử dụng
  • Làm thế nào để bạn lấy các giá trị dài trong Python?
  • Con số lớn nhất Python có thể xử lý là bao nhiêu?
  • Làm thế nào để Python lưu trữ số nguyên dài?
  • Số lượng dài trong Python là gì?

class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]

Điều này sẽ mang lại cho mỗi bàn tay một giá trị số mà thông qua Modulo có thể cho tôi biết có bao nhiêu vị vua trong tay hoặc có bao nhiêu trái tim. Ví dụ, bất kỳ bàn tay nào có năm hoặc nhiều câu lạc bộ trong đó sẽ chia đều cho 2^5; Bất kỳ bàn tay nào có bốn vị vua sẽ chia đều cho 59^4, v.v.

Vấn đề là một bàn tay bảy thẻ như Acadahaskdkhks có giá trị băm khoảng 62,7 triệu triệu, sẽ mất hơn 32 bit để thể hiện nội bộ. Có cách nào để lưu trữ số lượng lớn như vậy trong Python sẽ cho phép tôi thực hiện các hoạt động số học trên đó không?

Phụ trợ @unacademy • Dữ liệu @Amazon • Nền tảng @Practo | Viết về ngôn ngữ nội bộ và toán học trong khoa học máy tính

Khi bạn mã hóa bằng ngôn ngữ cấp thấp như C, bạn lo lắng về việc chọn đúng loại dữ liệu và vòng loại cho số nguyên của bạn; Ở mỗi bước, bạn cần phải suy nghĩ nếu

class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
3 sẽ đủ hoặc bạn nên đi cho một
class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
4 hoặc thậm chí cao hơn so với
class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
5. Nhưng trong khi mã hóa trong Python, bạn không cần phải lo lắng về những điều "tầm thường" này vì Python hỗ trợ các số nguyên có kích thước tùy ý.

Trong C, khi bạn cố gắng tính toán 2²⁰⁰⁰⁰ bằng cách sử dụng hàm

class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
6 tích hợp, nó cung cấp cho bạn
class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
7 làm đầu ra.

#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf

Nhưng đối với Python, nó là một miếng bánh 🎂

>>> 2 ** 20000
39802768403379665923543072061912024537047727804924259387134 ...
...
... 6021 digits long ...
...
6309376

Python phải làm một cái gì đó đẹp trong nội bộ để hỗ trợ các số nguyên có kích thước tùy ý và hôm nay chúng tôi tìm ra những gì dưới mui xe!

Đại diện và định nghĩa

Một số nguyên trong Python là một cấu trúc C được xác định như sau

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};

class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
8 là một macro mở rộng thành
class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
9 có cấu trúc sau

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;

Các loại khác có

class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]
8 là

  •     def HashVal(self):
          return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
    
    1
  •     def HashVal(self):
          return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
    
    2
  •     def HashVal(self):
          return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
    
    3

Điều này chỉ ra rằng một số nguyên, giống như

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
4 hoặc
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
5, có độ dài khác nhau và đây là cái nhìn sâu sắc đầu tiên của chúng tôi về cách nó có thể hỗ trợ các số nguyên dài.
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
6 sau khi mở rộng vĩ mô có thể được xem là

struct _longobject {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
    digit ob_digit[1];
};

Đây là một số trường meta trong cấu trúc

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
7, được sử dụng để đếm tham chiếu (thu gom rác), nhưng chúng tôi sẽ yêu cầu một bài viết riêng. Trường mà chúng tôi sẽ tập trung vào là
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
8 và ở một mức độ nào đó
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
9.

Giải mã ob_digit

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
8 là một mảng loại
#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf
1, được đánh máy từ
#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf
2, được phân bổ tĩnh cho chiều dài
#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf
3. Vì nó là một mảng,
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
8 chủ yếu là
#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf
5, con trỏ đến
#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf
1, và do đó nếu được yêu cầu có thể được đưa vào bất kỳ độ dài nào. Điều này làm cho Python có thể đại diện và xử lý các số nguyên dài.

Nói chung, trong các ngôn ngữ cấp thấp như C, độ chính xác của các số nguyên được giới hạn ở mức 64 bit, nhưng Python thực hiện các số nguyên chính xác tùy ý. Vì Python 3, tất cả các số nguyên được biểu diễn dưới dạng bignum và chúng chỉ bị giới hạn bởi bộ nhớ có sẵn của hệ thống máy chủ.

Giải mã ob_size

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
9 giữ số lượng các yếu tố trong
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
8. Để hiệu quả hơn trong khi phân bổ bộ nhớ thành mảng
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
8, các sự cung cấp quá mức của Python và sau đó dựa vào giá trị của
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
9 để xác định số lượng các phần tử thực tế được giữ trong mảng.

Kho

Một cách ngây thơ để lưu trữ một số nguyên chữ số là bằng cách thực sự lưu trữ một chữ số thập phân trong một mục của mảng và sau đó các hoạt động như bổ sung và trừ có thể được thực hiện giống như toán học lớp.

Với cách tiếp cận này, một số

>>> 2 ** 20000
39802768403379665923543072061912024537047727804924259387134 ...
...
... 6021 digits long ...
...
6309376
1 sẽ được lưu trữ dưới dạng

Cách tiếp cận này không hiệu quả vì chúng ta sẽ sử dụng tăng 32 bit chữ số (

#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf
2) để lưu trữ một chữ số thập phân thực sự chỉ dao động từ 0 đến 9 và có thể dễ dàng được biểu diễn bằng 4 bit, và trong khi viết một cái gì đó linh hoạt như Python, Một nhà phát triển cốt lõi phải tháo vát hơn thế này.

Vì vậy, chúng ta có thể làm tốt hơn không? Để chắc chắn, nếu không, bài viết này sẽ không giữ chỗ trên internet. Hãy đi sâu vào cách Python lưu trữ một số nguyên siêu dài.

Cách pythonic

Thay vì chỉ lưu trữ một chữ số thập phân trong mỗi mục của mảng

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
8, Python chuyển đổi số từ cơ sở 10 thành cơ sở 2³⁰ và gọi từng phần tử là
#include <stdio.h>
#include <math.h>

int main(void) {
  printf("%Lf\n", powl(2, 20000));
  return 0;
}

$ ./a.out
inf
1 dao động từ 0 đến 2³⁰ - 1.

Trong hệ thống số thập lục phân, cơ sở là 16 ~ 2⁴ Điều này có nghĩa là mỗi "chữ số" của một số thập lục phân dao động từ 0 đến 15 của hệ thống thập phân. Tương tự đối với Python, "Digit" nằm trong cơ sở 2³⁰ có nghĩa là nó sẽ nằm trong khoảng từ 0 đến 2³⁰ - 1 = 1073741823 của hệ thống thập phân.

Bằng cách này, Python sử dụng hiệu quả hầu hết tất cả không gian được phân bổ 32 bit mỗi chữ số và giữ cho chính nó tháo vát và vẫn thực hiện các hoạt động như bổ sung và trừ như toán học lớp.

Tùy thuộc vào nền tảng, Python sử dụng các mảng số nguyên không dấu 32 bit với các chữ số 30 bit hoặc các mảng số nguyên không dấu 16 bit với các chữ số 15 bit. Nó đòi hỏi một vài bit để thực hiện các hoạt động sẽ được thảo luận trong một số bài viết trong tương lai.

Ví dụ: 1152921504606846976

Như đã đề cập, đối với Python, một "chữ số" là cơ sở 2³⁰ do đó nếu bạn chuyển đổi

>>> 2 ** 20000
39802768403379665923543072061912024537047727804924259387134 ...
...
... 6021 digits long ...
...
6309376
5 thành cơ sở 2³⁰ bạn sẽ nhận được
>>> 2 ** 20000
39802768403379665923543072061912024537047727804924259387134 ...
...
... 6021 digits long ...
...
6309376
6.

1152921504606846976 = 0 * (2³⁰) ⁰ + 0 * (2³⁰) ¹ + 1 * (2³⁰) ² = 0 * (2³⁰)⁰ + 0 * (2³⁰)¹ + 1 * (2³⁰)²

Cấu trúc

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
6 cho giá trị này sẽ được giữ

  •     def HashVal(self):
          return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
    
    9 là
    >>> 2 ** 20000
    39802768403379665923543072061912024537047727804924259387134 ...
    ...
    ... 6021 digits long ...
    ...
    6309376
    
    9
  •     def HashVal(self):
          return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
    
    8 là
    struct _longobject {
        PyObject_VAR_HEAD
        digit ob_digit[1];
    };
    
    1

Tôi đã tạo ra một bản demo sẽ xuất hiện theo cách mà Python đang lưu trữ các số nguyên trong nội bộ và cũng có tham chiếu đến các thành viên cấu trúc như

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
9,
struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};
3, v.v.

Hoạt động trên các số nguyên siêu dài

Bây giờ chúng ta có một ý tưởng công bằng về cách Python hỗ trợ và thực hiện các số nguyên chính xác tùy ý của nó để hiểu làm thế nào các hoạt động toán học khác nhau xảy ra với chúng.

Phép cộng

Các số nguyên vẫn tồn tại "khôn ngoan về chữ số", điều này có nghĩa là sự bổ sung cũng đơn giản như những gì chúng ta học được ở trường lớp và mã nguồn của Python cho chúng ta thấy rằng đây chính xác là cách nó được thực hiện. Hàm có tên X_ADD trong Tệp LongObject.c thực hiện việc bổ sung hai số.

...
    for (i = 0; i < size_b; ++i) {
        carry += a->ob_digit[i] + b->ob_digit[i];
        z->ob_digit[i] = carry & PyLong_MASK;
        carry >>= PyLong_SHIFT;
    }
    for (; i < size_a; ++i) {
        carry += a->ob_digit[i];
        z->ob_digit[i] = carry & PyLong_MASK;
        carry >>= PyLong_SHIFT;
    }
    z->ob_digit[i] = carry;
...

Đoạn mã ở trên được lấy từ hàm

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};
4 và bạn có thể thấy rằng nó lặp lại trên các chữ số và thực hiện thêm chữ số-khôn ngoan và tính toán và truyền tải mang theo.

Mọi thứ trở nên thú vị khi kết quả của việc bổ sung là một số âm. Dấu hiệu của

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
9 là dấu hiệu của số nguyên, có nghĩa là, nếu bạn có số âm thì
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
9 sẽ âm. Giá trị tuyệt đối của
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
9 sẽ xác định số chữ số trong
    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
8.

Phép trừ

Tương tự như cách bổ sung được thực hiện, phép trừ cũng xảy ra theo chữ số. Hàm có tên x_sub trong Tệp LongObject.c thực hiện phép trừ hai số.

...
    for (i = 0; i < size_b; ++i) {
        borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
        z->ob_digit[i] = borrow & PyLong_MASK;
        borrow >>= PyLong_SHIFT;
        borrow &= 1; /* Keep only one sign bit */
    }
    for (; i < size_a; ++i) {
        borrow = a->ob_digit[i] - borrow;
        z->ob_digit[i] = borrow & PyLong_MASK;
        borrow >>= PyLong_SHIFT;
        borrow &= 1; /* Keep only one sign bit */
    }
...

Đoạn mã ở trên được lấy từ hàm

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};
9 và bạn có thể thấy cách nó lặp lại trên các chữ số và thực hiện phép trừ và tính toán và truyền bá Burrow. Rất giống với bổ sung thực sự.

Phép nhân

Một lần nữa, một cách ngây thơ để thực hiện phép nhân sẽ là những gì chúng ta học được trong toán học lớp nhưng nó sẽ không hiệu quả. Python, để giữ cho mọi thứ hiệu quả thực hiện thuật toán Karatsuba nhân lên hai số N-chữ số trong các bước cơ bản O (Nˡᵒᵍ³).

Thuật toán hơi phức tạp nằm ngoài phạm vi của bài viết này nhưng bạn có thể tìm thấy việc triển khai của nó trong các hàm k_mul và k_lopsided_mul trong tệp longobject.c.
k_lopsided_mul functions in file longobject.c.

Bộ phận và các hoạt động khác

Tất cả các hoạt động trên số nguyên được xác định trong tệp longoBject.c và nó rất đơn giản để định vị và theo dõi từng cái. CẢNH BÁO: Sẽ mất một thời gian để hiểu chi tiết từng người một số bỏng ngô trước khi bạn bắt đầu lướt qua.

Tối ưu hóa các số nguyên thường được sử dụng

Python preall phân biến các số nguyên nhỏ trong phạm vi từ -5 đến 256. Phân bổ này xảy ra trong quá trình khởi tạo và vì chúng tôi không thể cập nhật số nguyên (tính bất biến) các số nguyên được phân tách này là đơn lẻ và được tham chiếu trực tiếp thay vì phân bổ lại. Điều này có nghĩa là mỗi khi chúng ta sử dụng/tạo ra một số nguyên nhỏ, python thay vì phân bổ lại chỉ trả về tham chiếu của một cái được phân bổ.

Tối ưu hóa này có thể được theo dõi trong macro

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
0 và hàm get_small_int trong longobject.c. Bằng cách này, Python tiết kiệm rất nhiều không gian và tính toán cho các số nguyên thường được sử dụng.


Đây là bài viết thứ hai trong sê -ri Python Internals. Bài viết đầu tiên là cách tôi thay đổi con trăn của mình và làm cho nó trở nên đáng ngờ và nó giúp bạn thực hiện những bước đầu tiên trong mã nguồn của Python và mở đường cho bạn để trở thành nhà phát triển Python Core.

Bài viết này ban đầu được xuất bản trên blog của tôi - Làm thế nào Python thực hiện các số nguyên siêu dài ?.

Nếu bạn muốn đọc thêm các bài viết như thế này, hãy đăng ký nhận bản tin của tôi và nhận bài đăng được gửi trực tiếp vào hộp thư đến của bạn. Tôi viết về kỹ thuật, thiết kế hệ thống và một chút lập trình, mỗi thứ Sáu. Hãy cho tôi một tiếng hét @arpit_bhayani. Bạn có thể tìm thấy các bài viết trước của tôi @arpitbhayani.me/blog.

Làm thế nào để bạn lấy các giá trị dài trong Python?

Loại int (x) để chuyển đổi x thành số nguyên đơn giản. Nhập dài (x) để chuyển đổi x thành số nguyên dài. Loại float (x) để chuyển đổi x thành số điểm nổi.Type long(x) to convert x to a long integer. Type float(x) to convert x to a floating-point number.

Con số lớn nhất Python có thể xử lý là bao nhiêu?

Nó thường là 2^31 - 1 trên nền tảng 32 bit và 2^63 - 1 trên nền tảng 64 bit.2^63 - 1 on a 64-bit platform.

Làm thế nào để Python lưu trữ số nguyên dài?

Tuy nhiên, Python không sử dụng số bit cố định để lưu trữ số nguyên. Thay vào đó, Python sử dụng một số lượng bit khác nhau để lưu trữ số nguyên. Ví dụ, 8 bit, 16 bit, 32 bit, 64 bit, 128 bit, v.v. Số nguyên tối đa mà Python có thể đại diện phụ thuộc vào bộ nhớ có sẵn.uses a variable number of bits to store integers. For example, 8 bits, 16 bits, 32 bits, 64 bits, 128 bits, and so on. The maximum integer number that Python can represent depends on the memory available.

Số lượng dài trong Python là gì?

Long: Loại nguyên với chiều dài không giới hạn.Trong Python 2.2 trở lên, INT được tự động biến thành INT dài khi chúng tràn.Được bỏ kể từ Python 3.0, thay vào đó sử dụng loại int.Float: Đây là một số điểm nổi nhị phân.Integer type with unlimited length. In python 2.2 and later, Ints are automatically turned into long ints when they overflow. Dropped since Python 3.0, use int type instead. Float: This is a binary floating point number.