17. Số nguyên, số float và số phức

Các đối tượng số của Python là các đối tượng thông thường được triển khai chuyên biệt. Chúng tham gia vào cùng một mô hình đối tượng như danh sách, từ điển, hàm, lớp và mô-đun: mỗi giá trị có một tiêu đề đối tượng, một con trỏ kiểu, hành vi đếm tham chiếu và các vùng kiểu cho các phép toán.

Các loại số tích hợp chính là:

Loại Tên Python Đại diện chính
Số nguyên int Số nguyên có độ chính xác tùy ý
Boolean bool Lớp con Singleton củaint
Điểm nổi float C đôi
Phức tạp complex Cặp C đôi

Các loại này trông đơn giản ở cấp độ Python, nhưng mỗi loại đều có sự cân bằng quan trọng trong thời gian chạy.

17.1 Đối tượng số là đối tượng

Số nguyên Python thường không được lưu trữ dưới dạng số nguyên CPU thô trong các biến Python.python x = 42 Ở cấp độ CPython,xđề cập đến một đối tượng số nguyên Python.

Về mặt khái niệm:text x ---> PyLongObject object header integer payload Điều này cũng đúng với số float và số phức.python a = 1.5 b = 1 + 2j Về mặt khái niệm:```text a ---> PyFloatObject object header double value

b ---> PyComplexObject object header double real double imag Mô hình đối tượng cung cấp cho các số hành vi Python bình thường:python print(type(42)) print((42).class) print((42).bit_length())


## 17.2 Đối tượng số nguyên

Python`int`là độ chính xác tùy ý.```python
x = 10 ** 100
print(x)
```Giá tr không tràn  32 hoc 64 bit. CPython phát trin đại din ni b khi cn thiết.

Loi cp C thường được gi là`PyLongObject`.

V mt khái nim:```text
PyLongObject
    PyVarObject header
        ob_size
    digit array
```các`ob_size`trường mã hóa c s ch s bên trong và du. Mng ch s lưu tr giá tr tuyt đối trong mt cơ s ln.

Đây là lý do ti sao Python có th tính toán:```python
x = 2 ** 1000
y = x * x
print(y)
```không có tràn s nguyên.

Cái giá phi tr là s nguyên ln đòi hi nhiu b nh hơn và nhiu thi gian CPU hơn s nguyên máy.

## 17.3 Lưu trữ chữ số nguyên

CPython lưu tr mt s nguyên dưới dng nhiu ch s bên trong.

Mt mô hình đơn gin hóa:```text
value = sign * (d0 + d1 * base + d2 * base^2 + ...)
```Đối vi s nguyên nh, ch cn mt ch s.

Đối vi s nguyên ln, cn có nhiu ch s.

V mt khái nim:```text
42
    sign = positive
    digits = [42]

2**1000
    sign = positive
    digits = [d0, d1, d2, ...]
```Cách biu din này tương t như cách con người viết s thp phân dưới dng ch s, ngoi tr CPython s dng cơ s ni b ln hơn nhiu để đạt hiu qu.

Các phép toán s hc hot động trên các mng ch s này.```text
small int addition
    cheap

large int addition
    cost grows with number of digits

large int multiplication
    cost grows more quickly, with specialized algorithms for large cases
```## 17.4 Dấu nguyên

Du hiu được th hin thông qua siêu d liu kích thước, không phi dưới dng đối tượng Python riêng bit.

V mt khái nim:```text
ob_size > 0
    positive integer

ob_size == 0
    zero

ob_size < 0
    negative integer
```Mng ch s lưu tr độ ln.

Ví d:```text
123
    ob_size = positive digit count
    digits = magnitude

-123
    ob_size = negative digit count
    digits = magnitude
```Biu din này gi cho đối tượng nh gn.

## 17.5 Tính bất biến của số nguyên

S nguyên là bt biến.```python
x = 10
x += 1
```Điu này không làm thay đổi đối tượng s nguyên`10`. Nó to hoc truy xut mt đối tượng s nguyên khác và liên kết li`x`.

V mt khái nim:```text
x ---> int object 10

x += 1

x ---> int object 11
```Hành vi này hin th khi các đối tượng được chia s:```python
a = 10
b = a

a += 1

print(a)    # 11
print(b)    # 10

bvẫn đề cập đến đối tượng số nguyên ban đầu.

17.6 Tái sử dụng số nguyên nhỏ

CPython tái sử dụng một số đối tượng số nguyên nhỏ.```python a = 1 b = 1


Đây là một sự tối ưu hóa. Nó làm giảm sự phân bổ cho các giá trị chung.

Không dựa vào danh tính để so sánh giá trị số nguyên.

Chính xác:```python
if x == 1:
    ...
```Không đúng:```python
if x is 1:
    ...

iskiểm tra danh tính đối tượng.==kiểm tra đẳng thức số.

17.7 Đối tượng Booleanboollà một lớp con củaint.

print(isinstance(True, int))   # True
print(True + True)             # 2
``` chính xác hai đối tượng singleton boolean:```python
True
False
```Mối quan hệ loại :```text
bool
    subclass of int
```Điều này tồn tại  sự tương thích lịch sử  thực tế. Các giá trị Boolean hoạt động trong ngữ cảnh số, nhưng  nên sử dụng chúng cho các giá trị chân .```python
if ready:
    ...
```Còn hơn :```python
if ready == True:
    ...
``` cấp độ C,  mở rộng thường trả về các giá trị boolean với:```c
Py_RETURN_TRUE;
Py_RETURN_FALSE;
```Các macro này trả về các tham chiếu thuộc sở hữu của các đối tượng đơn lẻ.

## 17.8 Kiểm tra giá trị thực

Các đối tượng số tham gia kiểm tra giá trị thật.```python
bool(0)        # False
bool(1)        # True
bool(-1)       # True
bool(0.0)      # False
bool(0j)       # False
```Quy tắc cho các loại số rất đơn giản:```text
zero value
    false

nonzero value
    true
```Kiểm tra sự thật sử dụng máy móc giao thức loại.  cấp độ C, các kiểu số cung cấp hành vi thông qua các vị trí như chuyển đổi boolean.

## 17.9 Các phép toán số nguyên

Các phép toán số nguyên phổ biến bao gồm:```python
a + b
a - b
a * b
a // b
a % b
a ** b
a << n
a >> n
a & b
a | b
a ^ b
~a
```Những bản đồ này tới các khe số.

Về mặt khái niệm:```text
PyLong_Type
    nb_add
    nb_subtract
    nb_multiply
    nb_floor_divide
    nb_remainder
    nb_power
    nb_lshift
    nb_rshift
    nb_and
    nb_or
    nb_xor
    nb_invert
```Mỗi thao tác nhận các đối tượng Python  trả về một đối tượng Python.

Ngay cả khi kết quả khớp với từ máy, kết quả vẫn  đối tượng Python.

## 17.10 Phép chia số nguyên

Python  hai toán tử chia chính.```python
a / b     # true division
a // b    # floor division
```Đối với số nguyên:```python
print(5 / 2)     # 2.5
print(5 // 2)    # 2

/trả về một số float cho số nguyên thông thường.//trả về kết quả sàn.

Đối với các giá trị âm:python print(-5 // 2) # -3 print(-5 % 2) # 1 Danh tính giữ:text a == (a // b) * b + (a % b) với%mang theo quy ước về dấu hiệu theo yêu cầu của ngữ nghĩa Python.

Hoạt động bit 17.11

Các số nguyên hỗ trợ các phép toán bit như thể được biểu diễn dưới dạng phần bù hai với phần mở rộng dấu vô hạn.python x & y x | y x ^ y ~x x << n x >> n Ví dụ:python print(5 & 3) # 1 print(5 | 3) # 7 print(5 ^ 3) # 6 print(~5) # -6 Kết quả của~xsau:```text ~x == -x - 1


## 17.12 Phương thức số nguyên

Các phương thức số nguyên thể hiện các thuộc tính hữu ích của giá trị bên trong.```python
x = 1024

print(x.bit_length())
print(x.bit_count())

bit_lengthtrả về số bit cần thiết để biểu thị giá trị tuyệt đối.```python print((0).bit_length()) # 0 print((1).bit_length()) # 1 print((2).bit_length()) # 2 print((3).bit_length()) # 2


`bit_count`trả về số lượng dân số của giá trị tuyệt đối.```python
print((7).bit_count())      # 3
```Các phương pháp này thường ánh xạ hiệu quả tới các hoạt động chữ số bên trong  nội tại CPU nếu .

## 17.13 Chuyển đổi số nguyên thành byte

Các số nguyên  thể được chuyển đổi sang  từ các chuỗi byte.```python
x = 1024

data = x.to_bytes(2, byteorder="big")
print(data)

again = int.from_bytes(data, byteorder="big")
print(again)
```Điều này quan trọng đối với:```text
binary protocols
cryptography
file formats
network byte order
serialization
```Endianness phải  ràng.```python
x.to_bytes(4, "big")
x.to_bytes(4, "little")
```Cùng một số nguyên tạo ra các bố cục byte khác nhau tùy thuộc vào thứ tự byte.

## 17.14 Đối tượng nổi

Python`float`thường  một lớp bao quanh một C double.

Về mặt khái niệm:```text
PyFloatObject
    PyObject header
    double value
```Một đối tượng float  kích thước cố định.```python
x = 1.5
y = 2.25
print(x + y)
```Các hoạt động nổi được thực hiện thông qua các khe số  các hoạt động dấu phẩy động nền tảng.

Điểm mấu chốt: số float  số dấu phẩy động nhị phân gần đúng.

## 17.15 Dấu phẩy động nhị phân

Phân số thập phân thường không thể được biểu diễn chính xác dưới dạng nhị phân.```python
print(0.1 + 0.2)
```Điều này thường in:```text
0.30000000000000004
```Vấn đề  sự đại diện.`0.1`không  khai triển nhị phân hữu hạn, giống như`1/3`không  khai triển thập phân hữu hạn.

 vậy, giá trị được lưu trữ  số float nhị phân  thể biểu thị gần nhất.

Điều này ảnh hưởng đến sự bình đẳng:```python
print(0.1 + 0.2 == 0.3)    # False
```Sử dụng so sánh dựa trên dung sai cho công việc số gần đúng:```python
import math

math.isclose(0.1 + 0.2, 0.3)
```## 17.16 Giá trị đặc biệt thả nổi

Phao bao gồm các giá trị đặc biệt:```python
inf = float("inf")
nan = float("nan")
neg_inf = float("-inf")
```Infinity hoạt động như mong đợi trong nhiều so sánh:```python
print(inf > 1e308)     # True
```NaN  không bình thường:```python
nan = float("nan")

print(nan == nan)      # False
print(nan != nan)      # True
```NaN  nghĩa  không phải số.  không so sánh bằng chính .

Hành vi này tuân theo các quy tắc dấu phẩy động, không phải logic nhận dạng đối tượng thông thường.

## 17.17 Băm nổi và bình đẳng

Các loại số phối hợp bình đẳng  băm.```python
print(1 == 1.0)          # True
print(hash(1) == hash(1.0))
```Nếu hai đối tượng số so sánh bằng nhau thì chúng phải  cùng hàm băm.

Điều này cho phép từ điển hoạt động chính xác:```python
d = {}
d[1] = "int"
d[1.0] = "float"

print(d)
```Nhiệm vụ thứ hai cập nhật vị trí quan trọng tương tự `1 == 1.0`.

Sự đẳng thức số kiểu chéo này rất thuận tiện, nhưng   thể gây ngạc nhiên cho những người dùng mong đợi các khóa phân biệt loại.

## 17.18 Chuyển đổi thả nổi

Chuyển đổi:```python
float(1)
int(1.9)
round(1.9)

intcắt ngắn về 0:```python print(int(1.9)) # 1 print(int(-1.9)) # -1


`round`tuân theo quy tắc làm tròn của Python:```python
print(round(2.5))
print(round(3.5))
```Chuyển đổi dấu phẩy động sang số nguyên  thể làm mất thông tin nếu số float không thể hiện chính xác giá trị mong muốn.

Đối với số học tài chính thập phân, hãy sử dụng`decimal.Decimal`thay  thả nổi nhị phân.

## 17.19 Đối tượng phức tạp

Python`complex`lưu trữ hai giá trị dấu phẩy động:```text
PyComplexObject
    PyObject header
    double real
    double imag
``` dụ:```python
z = 3 + 4j

print(z.real)
print(z.imag)
```Phần thực  phần ảo  phần nổi.

Số phức hỗ trợ số học:```python
a = 1 + 2j
b = 3 + 4j

print(a + b)
print(a * b)
```Họ không hỗ trợ đặt hàng:```python
(1 + 2j) < (3 + 4j)    # TypeError
```Không  thứ tự tổng tự nhiên cho các số phức trong  hình số của Python.

## 17.20 Số học phức tạp

Phép nhân phức tạp sau:```text
(a + bi)(c + di) = (ac - bd) + (ad + bc)i
```Python xử  việc này bên trong việc triển khai kiểu phức tạp.

 dụ:```python
a = 1 + 2j
b = 3 + 4j

print(a * b)      # (-5+10j)
```Sự phân chia  quyền hạn cũng được hỗ trợ.

Đối với công việc tính toán nâng cao,`cmath`module cung cấp các hàm toán học nhận biết phức tạp.```python
import cmath

print(cmath.sqrt(-1))
```## 17.21 Tháp số

 hình số của Python  hệ thống phân cấp khái niệm:```text
numbers.Number
    numbers.Complex
        numbers.Real
            numbers.Rational
                numbers.Integral
```Các loại tích hợp gần như phù hợp như:

| Loại | Vai trò khái niệm |
| --------- | ----------------------------- |
|`complex`| Phức tạp |
|`float`| Thực tế |
|`int`| Tích phân |
|`bool`| Phân lớp tích phân trong thực tế |

các`numbers`module cung cấp các lớp  sở trừu tượng cho các giao thức số.

Hầu hết các hoạt động CPython thông thường sử dụng các khe kiểu cụ thể thay  gửi lớp  sở trừu tượng, nhưng hệ thống phân cấp giúp xác định hành vi dự kiến.

## 17.22 Các phép toán hỗn hợp số

Các phép toán số hỗn hợp tuân theo các quy tắc ép buộc  gửi đi.```python
print(1 + 2.5)       # 3.5
print(1 + 2j)        # (1+2j)
print(1.5 + 2j)      # (3.5+2j)
```Hướng mở rộng điển hình:```text
int -> float -> complex
```Đây  một  hình khái niệm. Việc triển khai thực tế sử dụng công văn hoạt động nhị phân giữa các loại toán hạng.

Đối với các lớp số do người dùng định nghĩa, trả về`NotImplemented`cho phép toán hạng khác thử hành vi được phản ánh.```python
class N:
    def __add__(self, other):
        return NotImplemented
```## 17,23`__index__`

`__index__` nghĩa  một đối tượng  thể được hiểu  một số nguyên chính xác để lập chỉ mục  cắt.```python
class Index:
    def __index__(self):
        return 2

xs = [10, 20, 30, 40]
print(xs[Index()])
```Điều này chặt chẽ hơn`__int__`.

Các trường hợp sử dụng bao gồm:```text
list indexes
slice bounds
range arguments
bit operations
low-level integer contexts
``` cấp độ C, điều này tương ứng với hành vi giao thức chỉ số nguyên.

## 17,24`__int__`, `__float__`, Và`__complex__`Các phương thức chuyển đổi cho phép các đối tượng giống số tùy chỉnh chuyển đổi thành các kiểu số có sẵn.```python
class Value:
    def __int__(self):
        return 10

    def __float__(self):
        return 10.5

    def __complex__(self):
        return 10.5 + 2j
```Cách sử dụng:```python
v = Value()

print(int(v))
print(float(v))
print(complex(v))
```Những chuyển đổi này tạo ra các đối tượng số tích hợp.

Chúng không tự động tạo kiểu tùy chỉnh đầy đủ bằng số. Các phương pháp số học vẫn cần được thực hiện riêng biệt.

## 17,25 Khe số

Hành vi số được thực hiện thông qua các vị trí.

Bảng slot khái niệm:```text
PyNumberMethods
    nb_add
    nb_subtract
    nb_multiply
    nb_remainder
    nb_divmod
    nb_power
    nb_negative
    nb_positive
    nb_absolute
    nb_bool
    nb_invert
    nb_lshift
    nb_rshift
    nb_and
    nb_xor
    nb_or
    nb_int
    nb_float
    nb_index
    nb_matrix_multiply
    nb_inplace_add
    ...
``` pháp Python ánh xạ vào bảng này.

|  pháp | Khái niệm máy đánh bạc |
| ---------- | --------------------- |
|`a + b`| cộng |
|`a - b`| phép trừ |
|`a * b`| phép nhân |
|`a @ b`| phép nhân ma trận |
|`-a`| phủ định |
|`abs(a)`| giá trị tuyệt đối |
|`bool(a)`| giá trị thật |
|`int(a)`| chuyển đổi số nguyên |
|`float(a)`| chuyển đổi thả nổi |
|`a << b`| dịch chuyển trái |

Bảng vị trí này   do tại sao các kiểu số mở rộng  tích hợp sẵn  thể tích hợp với  pháp Python.

## 17.26 Các thao tác số tại chỗ

Các nhà khai thác tại chỗ bao gồm:```python
x += y
x -= y
x *= y
x //= y
x **= y
```Đối với các số không thể thay đổi, các thao tác tại chỗ sẽ tạo một đối tượng mới  gắn lại tên.```python
x = 10
before = id(x)

x += 1
after = id(x)

print(before == after)   # usually False
```Đối với các đối tượng giống như số  thể thay đổi, một loại  thể thực hiện đột biến thực sự tại chỗ.

Tích hợp sẵn`int`, `float`, `complex` bất biến.

## 17,27 Thập phân và phân số

Thư viện chuẩn cung cấp các kiểu số bên ngoài các phần dựng sẵn cốt lõi.`decimal.Decimal`cung cấp số học dấu phẩy động thập phân.```python
from decimal import Decimal

print(Decimal("0.1") + Decimal("0.2"))

fractions.Fractioncung cấp số học hợp lý.```python from fractions import Fraction

print(Fraction(1, 3) + Fraction(1, 6))


S dng chúng khi ng nghĩa ca chúng phù hp vi vn đề:

| Cn | Loi |
| ----------------------------------- | ---------- |
| S nguyên tng quát |`int`|
| Công trình s khoa hc gn đúng |`float`|
| S hc phc tp |`complex`|
| S hc tài chính thp phân |`Decimal`|
| S hc hp lý chính xác |`Fraction`|

## 17.28 C API: Tạo số

To mt s nguyên:```c
PyObject *x = PyLong_FromLong(42);
if (x == NULL) {
    return NULL;
}
```To t loi C rng hơn:```c
PyObject *x = PyLong_FromLongLong(value);
```To phao:```c
PyObject *f = PyFloat_FromDouble(3.14);
if (f == NULL) {
    return NULL;
}
```To phc cht:```c
PyObject *z = PyComplex_FromDoubles(1.0, 2.0);
if (z == NULL) {
    return NULL;
}
```Mi tr v mt tài liu tham kho mi. Người gi s hu nó.

## 17.29 C API: Trích xuất số

Trích xut mt C dài:```c
long value = PyLong_AsLong(obj);
if (value == -1 && PyErr_Occurred()) {
    return NULL;
}
```Vic kim tra li quan trng vì`-1`có th là mt kết qu hp l.

Trích xut mt double:```c
double value = PyFloat_AsDouble(obj);
if (value == -1.0 && PyErr_Occurred()) {
    return NULL;
}
```Mt ln na, hãy kim tra trng thái ngoi l.

Đối vi các ng cnh ging như s nguyên, hãy s dng API chuyn đổi ch mc khi yêu cu ng nghĩa s nguyên chính xác.

## 17.30 Tràn ranh giới C

S nguyên Python có độ chính xác tùy ý. S nguyên C có chiu rng c định.

Chuyn đổi này có th tht bi:```c
long value = PyLong_AsLong(obj);
```nếu như`obj`quá ln đối vi C`long`.

Ví d cp độ Python:```python
x = 10 ** 100
```Giá tr này hp l dưới dng Python`int`, nhưng có th không va vi bt k loi s nguyên C nào.

Mã m rng C phi x lý li tràn.

Mt li ph biến là gi s Python`int`luôn phù hp vi`int`, `long`, hoc`size_t`.

## 17.31 Ghi chú về Hiệu suất

Hiu sut s ph thuc vào đại din.

S hc s nguyên nh được ti ưu hóa nhưng vn hot động trên các đối tượng Python.

Mt vòng lp cht ch:```python
total = 0

for i in range(10_000_000):
    total += i
```thc hin nhiu thao tác cp Python:```text
load total
load i
integer addition
create or retrieve result integer
store total
loop control
```Tc độ này chm hơn nhiu so vi C tương đương trên s nguyên máy thô.

Đối vi các mng s ln, hãy s dng các thư vin chuyên bit để lưu tr các giá tr thô mt cách gn gàng, chng hn như`array`, `memoryview`hoc NumPy.

Các kiu s tích hp ca Python ti ưu hóa ng nghĩa vô hướng, ch không phi tính toán vectơ s dày đặc.

## 17.32 Ghi chú bộ nhớ

Danh sách các s nguyên lưu tr các tham chiếu đến các đối tượng s nguyên.```python
xs = [1, 2, 3, 4]
```V mt khái nim:```text
list
    [ptr][ptr][ptr][ptr]
      |    |    |    |
      v    v    v    v
     int  int  int  int
```Mt mng lưu tr các giá tr thô:```python
from array import array

xs = array("i", [1, 2, 3, 4])
```V mt khái nim:```text
array
    [int][int][int][int]
```Đây là lý do ti sao mng tiết kim b nh hơn đối vi d liu s ln đồng nht.

## 17.33 Những cạm bẫy số thường gặp

| Cm by | Ví d | Cách tiếp cn tt hơn |
| -------------------------------------- | ------------------------------- | ----------------------------- |
| s dng`is`cho các con s |`x is 1000`                     | `x == 1000`|
| Mong đợi độ chính xác thp phân t float |`0.1 + 0.2 == 0.3`              | `math.isclose`hoc`Decimal`|
| kiên trì`hash()`                    | `hash(x)`như ID n định |`hashlib`|
| Gi s Python int phù hp vi C long |`PyLong_AsLong`b chn | Kim tra tràn |
| S dng danh sách cho mng s dày đặc |`[0] * n`cho d liu s khng l |`array`hoc NumPy |
| So sánh NaN thông thường |`nan == nan`| S dng`math.isnan`|
| B qua chi phí tăng trưởng s nguyên | sc mnh to ln trong con đường nóng bng | Xem xét gii hn thut toán |

## 17.34 Mô hình tinh thần

S dng mô hình này:```text
int
    immutable arbitrary-precision integer
    variable-size digit array
    no fixed overflow
    cost grows with magnitude

bool
    singleton subclass of int
    truth-value type
    values are True and False

float
    immutable wrapper around C double
    approximate binary floating-point
    supports inf and nan

complex
    immutable pair of doubles
    real and imaginary parts
    arithmetic supported
    ordering unsupported
``` cp độ CPython:```text
numeric operation
    dispatch through type slots
    operate on concrete numeric representation
    allocate or return result object
    manage references
```##17.35 Tóm tắt

CPython trin khai s nguyên, s float và s phc dưới dng đối tượng Python có b cc C chuyên dng.`int`s dng b lưu tr có độ chính xác tùy ý, do đó, nó tránh được tình trng tràn chiu rng c định nhưng phi tr chi phí tăng theo kích thước giá tr.`float`bao bc mt C double và kế tha hành vi du phy động nh phân.`complex`lưu tr hai s nhân đôi và h tr s hc phc tp.

Nhng loi s này là bt biến. Các thao tác to đối tượng kết qu thay vì thay đổi toán hng. Hành vi ca chúng được tích hp thông qua các khe s, giao thc chuyn đổi, quy tc băm và chc năng API C.