Làm thế nào để bạn lấy bit trong python?

Toán tử bitwise được sử dụng để so sánh các số [nhị phân]

OperatorNameDescription& ANDĐặt từng bit thành 1 nếu cả hai bit đều là 1. ORĐặt từng bit thành 1 nếu một trong hai bit là 1 ^XORĐặt từng bit thành 1 nếu chỉ một trong hai bit là 1~ NOTĐảo ngược tất cả các bit 2 = 15 [có nghĩa là 0000 1111]
#!/usr/bin/python

a = 60            # 60 = 0011 1100 
b = 13            # 13 = 0000 1101 
c = 0

c = a & b;        # 12 = 0000 1100
print "Line 1 - Value of c is ", c

c = a | b;        # 61 = 0011 1101 
print "Line 2 - Value of c is ", c

c = a ^ b;        # 49 = 0011 0001
print "Line 3 - Value of c is ", c

c = ~a;           # -61 = 1100 0011
print "Line 4 - Value of c is ", c

c = a > 2;       # 15 = 0000 1111
print "Line 6 - Value of c is ", c

Khi bạn thực hiện chương trình trên, nó tạo ra kết quả sau -

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15

python_basic_operators. htm

peek đọc từ vị trí bit hiện tại pos trong chuỗi bit theo chuỗi fmt hoặc số nguyên và trả về kết quả. Vị trí bit không thay đổi

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
0

Nó đọc từ vị trí bit hiện tại trong chuỗi bit theo chuỗi định dạng và trả về một kết quả duy nhất

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
1

Chạy mẫu bên dưới cho thấy nó tăng 4 bit mỗi khi chúng tôi đọc một số hex

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
2

Nếu chúng ta đọc 4 bit và xuất nó dưới dạng định dạng nhị phân

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
3

Đầu ra dưới dạng một số nguyên không dấu khi chúng ta đọc 4 bit mỗi lần và tăng dần

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
4

pos/bitpos là thuộc tính đọc và ghi để thiết lập và lấy vị trí bit hiện tại trong chuỗi bit. Có thể được đặt thành bất kỳ giá trị nào từ 0 đến len

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
5

Đoạn mã sau đọc trong video. mp4 một byte tại một thời điểm, chuyển đổi nó thành ký tự và sau đó đặt nó vào danh sách. Nó chỉ đọc 180 byte đầu tiên

Máy tính lưu trữ tất cả các loại thông tin dưới dạng dòng các chữ số nhị phân được gọi là bit. Cho dù bạn đang làm việc với văn bản, hình ảnh hay video, tất cả chúng đều biến thành số một và số không. Toán tử bitwise của Python cho phép bạn thao tác các bit dữ liệu riêng lẻ đó ở mức chi tiết nhất

Bạn có thể sử dụng toán tử bitwise để thực hiện các thuật toán như nén, mã hóa và phát hiện lỗi cũng như để kiểm soát các thiết bị vật lý trong dự án Raspberry Pi của bạn hoặc ở nơi khác. Thông thường, Python cô lập bạn khỏi các bit cơ bản với mức độ trừu tượng cao. Bạn có nhiều khả năng tìm thấy hương vị quá tải của các toán tử bitwise trong thực tế. Nhưng khi bạn làm việc với chúng ở dạng ban đầu, bạn sẽ ngạc nhiên bởi những điều kỳ quặc của chúng

Trong hướng dẫn này, bạn sẽ học cách

  • Sử dụng các toán tử bitwise Python để thao tác các bit riêng lẻ
  • Đọc và ghi dữ liệu nhị phân theo cách bất khả tri trên nền tảng
  • Sử dụng bitmasks để đóng gói thông tin trên một byte đơn
  • Quá tải toán tử bitwise Python trong các loại dữ liệu tùy chỉnh
  • Ẩn tin nhắn bí mật trong hình ảnh kỹ thuật số

Để lấy mã nguồn hoàn chỉnh của ví dụ thủy ấn kỹ thuật số và để trích xuất một điều bí mật ẩn trong một hình ảnh, hãy nhấp vào liên kết bên dưới

Lấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về các toán tử bitwise của Python trong hướng dẫn này

Tổng quan về toán tử Bitwise của Python

Python đi kèm với một số loại toán tử khác nhau, chẳng hạn như toán tử số học, logic và so sánh. Bạn có thể coi chúng như các hàm tận dụng cú pháp tiền tố và trung tố nhỏ gọn hơn

Ghi chú. Python không bao gồm các toán tử hậu tố như toán tử tăng [

>>> [age >= 18] & ~is_self_excluded
0
9] hoặc giảm [
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
0] có sẵn trong C

Các toán tử bitwise trông gần như giống nhau trên các ngôn ngữ lập trình khác nhau

Toán tửVí dụÝ nghĩa_______91

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
2Bitwise AND
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
3
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
4Bitwise OR
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
5
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
6Bitwise XOR [độc quyền OR]
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
7
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
8Bitwise NOT
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
9
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
900Bitwise left shift
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
901
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
902Bitwise shift right

Như bạn có thể thấy, chúng được biểu thị bằng các ký hiệu lạ thay vì các từ. Điều này làm cho chúng nổi bật trong Python vì ít dài dòng hơn bạn có thể thấy. Bạn có thể sẽ không thể hiểu được ý nghĩa của chúng chỉ bằng cách nhìn vào chúng

Ghi chú. Nếu bạn đến từ một ngôn ngữ lập trình khác chẳng hạn như Java, thì bạn sẽ nhận thấy ngay rằng Python thiếu toán tử dịch chuyển phải không dấu được biểu thị bằng ba dấu lớn hơn [

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
903]

Điều này liên quan đến cách Python nội bộ. Vì các số nguyên trong Python có thể có vô số bit nên bit dấu không có vị trí cố định. Trên thực tế, không có chút dấu hiệu nào trong Python

Hầu hết các toán tử bitwise là nhị phân, có nghĩa là chúng mong đợi hai toán hạng hoạt động cùng, thường được gọi là toán hạng bên trái và toán hạng bên phải. Bitwise NOT [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
7] là toán tử bitwise đơn nguyên duy nhất vì nó chỉ mong đợi một toán hạng

Tất cả các toán tử bitwise nhị phân đều có toán tử ghép tương ứng thực hiện phép gán tăng cường

Toán tửVí dụTương đương với_______1905

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
906
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
907
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
908
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
909
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
910
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
911
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
912
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
913
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
914
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
915
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
916
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
917
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
918
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
919

Đây là các ký hiệu tốc ký để cập nhật toán hạng bên trái tại chỗ

Đó là tất cả những gì có trong cú pháp toán tử bitwise của Python. Bây giờ bạn đã sẵn sàng xem xét kỹ hơn từng toán tử để hiểu chúng hữu ích nhất ở đâu và cách bạn có thể sử dụng chúng. Trước tiên, bạn sẽ được xem lại nhanh về hệ thống nhị phân trước khi xem xét hai loại toán tử bitwise. toán tử logic theo bit và toán tử dịch chuyển theo bit

Loại bỏ các quảng cáo

Hệ thống nhị phân trong năm phút

Trước khi tiếp tục, hãy dành một chút thời gian để củng cố kiến ​​thức của bạn về hệ thống nhị phân, đây là điều cần thiết để hiểu các toán tử bitwise. Nếu bạn đã cảm thấy thoải mái với nó, hãy tiếp tục và chuyển sang phần bên dưới

Tại sao sử dụng nhị phân?

Có vô số cách biểu diễn số. Từ thời cổ đại, con người đã phát triển các ký hiệu khác nhau, chẳng hạn như chữ số La Mã và chữ tượng hình Ai Cập. Hầu hết các nền văn minh hiện đại sử dụng ký hiệu vị trí, hiệu quả, linh hoạt và rất phù hợp để thực hiện số học

Một tính năng đáng chú ý của bất kỳ hệ thống vị trí nào là cơ sở của nó, đại diện cho số chữ số có sẵn. Mọi người thường thích hệ đếm cơ số 10, còn được gọi là hệ thập phân, bởi vì nó hoạt động tốt với việc đếm trên đầu ngón tay

Mặt khác, máy tính coi dữ liệu là một loạt các số được biểu thị trong hệ thống cơ số hai chữ số, thường được gọi là hệ thống nhị phân. Những số như vậy bao gồm chỉ có hai chữ số, số không và một

Ghi chú. Trong sách toán, cơ sở của một chữ số thường được biểu thị bằng một chỉ số xuất hiện bên dưới đường cơ sở một chút, chẳng hạn như 4210

Ví dụ: số nhị phân 100111002 tương đương với 15610 trong hệ cơ số mười. Vì có mười chữ số trong hệ thập phân—từ 0 đến 9—nên thường cần ít chữ số hơn để viết cùng một số trong cơ số mười so với cơ số hai

Ghi chú. Bạn không thể biết một hệ thống số chỉ bằng cách nhìn vào các chữ số của một số nhất định

Ví dụ: số thập phân 10110 chỉ sử dụng các chữ số nhị phân. Nhưng nó đại diện cho một giá trị hoàn toàn khác so với đối tác nhị phân của nó, 1012, tương đương với 510

Hệ thống nhị phân yêu cầu nhiều không gian lưu trữ hơn hệ thống thập phân nhưng ít phức tạp hơn nhiều khi triển khai trong phần cứng. Mặc dù bạn cần nhiều khối xây dựng hơn nhưng chúng dễ tạo hơn và có ít loại hơn. Điều đó giống như chia mã của bạn thành nhiều phần mô-đun hơn và có thể tái sử dụng

Tuy nhiên, quan trọng hơn, hệ thống nhị phân hoàn hảo cho các thiết bị điện tử, giúp dịch các chữ số thành các mức điện áp khác nhau. Vì điện áp thích dao động lên xuống do nhiều loại nhiễu khác nhau, nên bạn muốn giữ khoảng cách vừa đủ giữa các điện áp liên tiếp. Nếu không, tín hiệu có thể bị méo

Bằng cách chỉ sử dụng hai trạng thái, bạn làm cho hệ thống trở nên đáng tin cậy hơn và chống lại tiếng ồn. Ngoài ra, bạn có thể tăng điện áp, nhưng điều đó cũng sẽ làm tăng mức tiêu thụ điện năng, điều mà bạn chắc chắn muốn tránh

Nhị phân hoạt động như thế nào?

Hãy tưởng tượng trong một khoảnh khắc rằng bạn chỉ có hai ngón tay để đếm. Bạn có thể đếm một số không, một và hai. Nhưng khi bạn hết ngón tay, bạn cần ghi lại số lần bạn đã đếm đến hai và sau đó bắt đầu lại cho đến khi bạn đếm lại hai

DecimalFingersEightsFoursTwosOnesBinary010✊000002110☝️000112210✌️0010102310✌️+☝️0011112410✌️✌️01001002510✌️✌️+☝️01011012610✌️✌️+✌️01101102710✌️✌️+✌️+☝️01111112810✌️✌️✌️✌️100010002910✌️✌️✌️✌️+☝️1001100121010✌️✌️✌️✌️+✌️1010101021110

Mỗi lần bạn viết ra một cặp ngón tay khác, bạn cũng cần nhóm chúng theo lũy thừa của hai, đây là cơ sở của hệ thống. Ví dụ: để đếm đến mười ba, bạn sẽ phải sử dụng cả hai ngón tay của mình sáu lần rồi sử dụng một ngón tay nữa. Các ngón tay của bạn có thể được sắp xếp thành một tám, một bốn và một một

Những lũy ​​thừa của hai tương ứng với các vị trí chữ số trong một số nhị phân và cho bạn biết chính xác bit nào sẽ bật. Chúng phát triển từ phải sang trái, bắt đầu từ bit ít quan trọng nhất, xác định xem số đó là chẵn hay lẻ

Ký hiệu vị trí giống như đồng hồ đo quãng đường trong ô tô của bạn. Khi một chữ số ở một vị trí cụ thể đạt đến giá trị tối đa của nó, là một trong hệ thống nhị phân, nó sẽ chuyển sang 0 và một chữ số sẽ chuyển sang bên trái. Điều này có thể có hiệu ứng xếp tầng nếu đã có một số chữ số ở bên trái của chữ số

Cách máy tính sử dụng nhị phân

Bây giờ bạn đã biết các nguyên tắc cơ bản của hệ thống nhị phân và tại sao máy tính sử dụng nó, bạn đã sẵn sàng tìm hiểu cách chúng biểu diễn dữ liệu với nó

Trước khi bất kỳ phần thông tin nào có thể được tái tạo ở dạng kỹ thuật số, bạn phải chia nhỏ thông tin đó thành các số và sau đó chuyển đổi chúng sang hệ thống nhị phân. Ví dụ: văn bản thuần túy có thể được coi là một chuỗi ký tự. Bạn có thể gán một số tùy ý cho mỗi ký tự hoặc chọn mã hóa ký tự hiện có, chẳng hạn như ASCII, ISO-8859-1 hoặc UTF-8

Trong Python, các chuỗi được biểu diễn dưới dạng mảng các điểm mã Unicode. Để tiết lộ các giá trị thứ tự của chúng, hãy gọi

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
920 trên mỗi ký tự

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
0

Các số kết quả xác định duy nhất các ký tự văn bản trong không gian Unicode, nhưng chúng được hiển thị ở dạng thập phân. Bạn muốn viết lại chúng bằng các chữ số nhị phân

Ký tự Điểm mã thập phân Điểm mã nhị phân€836410100000101011002u1171011101012r1141011100102o1111011011112

Lưu ý rằng độ dài bit, là số chữ số nhị phân, thay đổi rất nhiều giữa các ký tự. Kí hiệu đồng euro [

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
921] yêu cầu mười bốn bit, trong khi các ký tự còn lại có thể vừa với bảy bit

Ghi chú. Đây là cách bạn có thể kiểm tra độ dài bit của bất kỳ số nguyên nào trong Python

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
9

Nếu không có một cặp dấu ngoặc đơn xung quanh số, nó sẽ được coi là một chữ số dấu phẩy động với dấu thập phân

Độ dài bit thay đổi có vấn đề. Ví dụ: nếu bạn đặt các số nhị phân đó cạnh nhau trên một đĩa quang, thì bạn sẽ có một dòng dài các bit không có ranh giới rõ ràng giữa các ký tự

100000101011001110101111001011011112

Một cách để biết cách diễn giải thông tin này là chỉ định các mẫu bit có độ dài cố định cho tất cả các ký tự. Trong điện toán hiện đại, đơn vị thông tin nhỏ nhất, được gọi là octet hoặc byte, bao gồm 8 bit có thể lưu trữ 256 giá trị riêng biệt

Bạn có thể đệm các điểm mã nhị phân của mình bằng các số 0 đứng đầu để biểu thị chúng dưới dạng byte

Ký tự Điểm mã thập phân Điểm mã nhị phân€83641000100000 101011002u1171000000000 011101012r1141000000000 011100102o1111000000000 011011112

Bây giờ mỗi ký tự chiếm hai byte hoặc 16 bit. Tổng cộng, văn bản gốc của bạn có kích thước gần gấp đôi, nhưng ít nhất nó được mã hóa một cách đáng tin cậy

Bạn có thể sử dụng mã hóa Huffman để tìm các mẫu bit rõ ràng cho mọi ký tự trong một văn bản cụ thể hoặc sử dụng mã hóa ký tự phù hợp hơn. Ví dụ: để tiết kiệm dung lượng, UTF-8 cố ý ưu tiên các chữ cái Latinh hơn các ký hiệu mà bạn ít có khả năng tìm thấy trong văn bản tiếng Anh

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
3

Được mã hóa theo tiêu chuẩn UTF-8, toàn bộ văn bản chiếm 6 byte. Vì UTF-8 là một siêu bộ của ASCII, nên các chữ cái

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
922,
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
923 và
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
924 chiếm một byte mỗi ký tự, trong khi ký hiệu euro chiếm ba byte trong mã hóa này

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7

Các loại thông tin khác có thể được số hóa tương tự như văn bản. Hình ảnh raster được tạo thành từ các pixel, với mỗi pixel có các kênh biểu thị cường độ màu dưới dạng số. Dạng sóng âm thanh chứa các số tương ứng với áp suất không khí tại một khoảng thời gian lấy mẫu nhất định. Các mô hình ba chiều được xây dựng từ các hình dạng hình học được xác định bởi các đỉnh của chúng, v.v.

Vào cuối ngày, mọi thứ đều là một con số

Loại bỏ các quảng cáo

Toán tử logic bitwise

Bạn có thể sử dụng các toán tử bitwise để thực hiện trên các bit riêng lẻ. Điều đó tương tự với việc sử dụng các toán tử logic như

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
925,
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
926 và
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
927, nhưng ở mức bit. Sự tương đồng giữa các toán tử bitwise và logic vượt xa điều đó

Có thể đánh giá các biểu thức Boolean bằng các toán tử bit thay vì các toán tử logic, nhưng việc sử dụng quá mức như vậy thường không được khuyến khích. Nếu bạn quan tâm đến chi tiết, thì bạn có thể mở rộng hộp bên dưới để tìm hiểu thêm

Đánh giá biểu thức Boolean bằng toán tử bitwiseHiển thị/Ẩn

Cách thông thường để chỉ định các biểu thức Boolean ghép trong Python là sử dụng các toán tử logic kết nối các vị từ liền kề, như thế này

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
1

Tại đây, bạn kiểm tra xem người dùng có đủ mười tám tuổi trở lên hay không và liệu họ có chọn không tham gia cờ bạc hay không. Bạn có thể viết lại điều kiện đó bằng toán tử bitwise

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
2

Mặc dù biểu thức này đúng về mặt cú pháp, nhưng có một vài vấn đề với nó. Đầu tiên, nó được cho là ít đọc hơn. Thứ hai, nó không hoạt động như mong đợi đối với tất cả các nhóm dữ liệu. Bạn có thể chứng minh điều đó bằng cách chọn các giá trị toán hạng cụ thể

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
3

Biểu thức được tạo bởi các toán tử theo bit ước tính thành

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
928, trong khi biểu thức tương tự được tạo từ các toán tử logic ước tính thành
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
929. Đó là bởi vì các toán tử bitwise tiếp quản các toán tử so sánh, thay đổi cách diễn giải toàn bộ biểu thức

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
6

Như thể ai đó đặt dấu ngoặc đơn ẩn xung quanh các toán hạng sai. Để khắc phục điều này, bạn có thể đặt dấu ngoặc đơn rõ ràng, điều này sẽ thực thi đúng thứ tự đánh giá

>>>

>>> [age >= 18] & ~is_self_excluded
0

Tuy nhiên, bạn không còn nhận được kết quả Boolean nữa. Các toán tử bitwise của Python được thiết kế chủ yếu để hoạt động với các số nguyên, vì vậy các toán hạng của chúng sẽ tự động được truyền nếu cần. Điều này có thể không phải lúc nào cũng có thể, mặc dù

Mặc dù bạn có thể sử dụng các số nguyên trung thực và giả trong ngữ cảnh Boolean, nhưng đó là một phản mẫu đã biết có thể khiến bạn mất nhiều giờ để gỡ lỗi không cần thiết. Tốt hơn hết là bạn nên theo Zen of Python để tránh rắc rối cho mình

Cuối cùng nhưng không kém phần quan trọng, bạn có thể cố ý muốn sử dụng các toán tử bitwise để vô hiệu hóa việc đánh giá ngắn mạch các biểu thức Boolean. Biểu thức sử dụng toán tử logic được đánh giá lười biếng từ trái sang phải. Nói cách khác, phép đánh giá dừng ngay khi biết kết quả của toàn bộ biểu thức

>>>

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True

Trong ví dụ thứ hai, toán hạng bên phải hoàn toàn không được gọi vì giá trị của toàn bộ biểu thức đã được xác định bởi giá trị của toán hạng bên trái. Bất kể toán hạng đúng là gì, nó sẽ không ảnh hưởng đến kết quả, vì vậy không có ích gì khi gọi nó trừ khi bạn dựa vào các tác dụng phụ

Có những thành ngữ, chẳng hạn như quay trở lại giá trị mặc định, tận dụng đặc thù này

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
90

Một biểu thức Boolean lấy giá trị của toán hạng được đánh giá cuối cùng. Toán hạng trở thành true hoặc false bên trong biểu thức nhưng vẫn giữ nguyên kiểu và giá trị ban đầu của nó sau đó. Cụ thể, một số nguyên dương ở bên trái được lan truyền, trong khi số 0 bị loại bỏ

Không giống như các đối tác logic của chúng, các toán tử bitwise được đánh giá một cách háo hức

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
91

Mặc dù biết toán hạng bên trái là đủ để xác định giá trị của toàn bộ biểu thức, nhưng tất cả các toán hạng luôn được đánh giá vô điều kiện

Trừ khi bạn có lý do chính đáng và biết mình đang làm gì, bạn chỉ nên sử dụng toán tử bitwise để kiểm soát bit. Nếu không thì quá dễ để hiểu sai. Trong hầu hết các trường hợp, bạn sẽ muốn chuyển số nguyên làm đối số cho toán tử bitwise

Bitwise AND

Toán tử AND theo bit [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
1] thực hiện kết hợp logic trên các bit tương ứng trong toán hạng của nó. Đối với mỗi cặp bit chiếm cùng một vị trí trong hai số, nó chỉ trả về một số khi cả hai bit được bật

Mẫu bit kết quả là giao điểm của các đối số của toán tử. Nó có hai bit được bật ở các vị trí mà cả hai toán hạng đều là một. Ở tất cả những nơi khác, ít nhất một trong các đầu vào có bit 0

Về mặt số học, điều này tương đương với tích của hai giá trị bit. Bạn có thể tính toán AND theo chiều bit của các số a và b bằng cách nhân các bit của chúng tại mọi chỉ số i

Đây là một ví dụ cụ thể

Biểu thức Giá trị nhị phân Giá trị thập phân ____193110011100215610

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
93211010025210
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
21010022010

Một nhân với một cho một, nhưng bất cứ điều gì nhân với 0 sẽ luôn dẫn đến kết quả bằng 0. Ngoài ra, bạn có thể lấy hai bit trong mỗi cặp. Lưu ý rằng khi các toán hạng có độ dài bit không bằng nhau, toán hạng ngắn hơn sẽ tự động được đệm bằng các số 0 ở bên trái

Bitwise HOẶC

Toán tử OR theo bit [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
3] thực hiện phân tách logic. Đối với mỗi cặp bit tương ứng, nó trả về một nếu ít nhất một trong số chúng được bật

Mẫu bit kết quả là sự kết hợp của các đối số của toán tử. Nó có năm bit được bật khi một trong hai toán hạng có một. Chỉ có sự kết hợp của hai số 0 mới cho số 0 ở đầu ra cuối cùng

Số học đằng sau nó là sự kết hợp của tổng và tích của các giá trị bit. Để tính toán OR theo bit của các số a và b, bạn cần áp dụng công thức sau cho các bit của chúng tại mọi chỉ số i

Đây là một ví dụ hữu hình

Biểu thức Giá trị nhị phân Giá trị thập phân ____193110011100215610

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
93211010025210
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
410111100218810

Nó gần giống như tổng của hai bit nhưng được kẹp ở đầu cao hơn để nó không bao giờ vượt quá giá trị của một. Bạn cũng có thể lấy hai bit trong mỗi cặp để có kết quả tương tự

Loại bỏ các quảng cáo

Bitwise XOR

Không giống như bitwise , và , toán tử XOR bitwise [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
5] không có đối chiếu logic trong Python. Tuy nhiên, bạn có thể mô phỏng nó bằng cách xây dựng trên các toán tử hiện có

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
92

Nó đánh giá hai điều kiện loại trừ lẫn nhau và cho bạn biết liệu một trong số chúng có được đáp ứng hay không. Ví dụ: một người có thể là trẻ vị thành niên hoặc người lớn nhưng không thể đồng thời là cả hai. Ngược lại, một người không phải là trẻ vị thành niên cũng không phải là người lớn thì không thể. Sự lựa chọn là bắt buộc

Tên XOR là viết tắt của từ “độc quyền hoặc” vì nó thực hiện phân tách độc quyền trên các cặp bit. Nói cách khác, mỗi cặp bit phải chứa các giá trị bit đối lập để tạo ra một

Trực quan, đó là sự khác biệt đối xứng của các đối số của toán tử. Có ba bit được bật trong kết quả mà cả hai số có giá trị bit khác nhau. Các bit ở các vị trí còn lại bị triệt tiêu vì chúng giống nhau

Tương tự như toán tử OR theo bit, phép tính số học của XOR liên quan đến tổng. Tuy nhiên, trong khi bit OR kẹp các giá trị tại một, thì toán tử XOR bao quanh chúng bằng một tổng modulo hai

Modulo là hàm của hai số—số bị chia và số chia—thực hiện phép chia và trả về phần dư của nó. Trong Python, có một toán tử modulo tích hợp được biểu thị bằng dấu phần trăm [

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
939]

Một lần nữa, bạn có thể xác nhận công thức bằng cách xem ví dụ

Biểu thức Giá trị nhị phân Giá trị thập phân ____193110011100215610

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
93211010025210
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
610101000216810

Tổng của hai số 0 hoặc hai số một chia cho hai sẽ được một số nguyên, vì vậy kết quả có số dư bằng 0. Tuy nhiên, khi bạn chia tổng của hai giá trị bit khác nhau cho hai, bạn sẽ nhận được một phân số có phần còn lại là một. Một công thức đơn giản hơn cho toán tử XOR là hiệu giữa giá trị lớn nhất và giá trị nhỏ nhất của cả hai bit trong mỗi cặp

Bitwise KHÔNG

Toán tử logic bitwise cuối cùng là toán tử NOT bitwise [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
7], chỉ mong đợi một đối số, làm cho nó trở thành toán tử bitwise đơn phương duy nhất. Nó thực hiện phép phủ định logic trên một số đã cho bằng cách lật tất cả các bit của nó

Các bit đảo ngược là phần bù của một, biến số 0 thành số 1 và số 1 thành số 0. Nó có thể được biểu diễn bằng số học dưới dạng phép trừ các giá trị bit riêng lẻ từ một

Đây là một ví dụ hiển thị một trong những số được sử dụng trước đây

Biểu thức Giá trị nhị phân Giá trị thập phân ____193110011100215610

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
8110001129910

Mặc dù toán tử NOT bitwise dường như là đơn giản nhất trong số chúng, nhưng bạn cần hết sức thận trọng khi sử dụng nó trong Python. Mọi thứ bạn đã đọc cho đến nay đều dựa trên giả định rằng các số được biểu diễn bằng số nguyên không dấu

Ghi chú. Các kiểu dữ liệu không dấu không cho phép bạn lưu trữ các số âm như -273 vì không có khoảng trống cho dấu trong mẫu bit thông thường. Cố gắng làm như vậy sẽ dẫn đến lỗi biên dịch, ngoại lệ thời gian chạy hoặc tràn số nguyên tùy thuộc vào ngôn ngữ được sử dụng

Mặc dù có nhiều cách để mô phỏng, nhưng Python không hỗ trợ chúng một cách tự nhiên. Điều đó có nghĩa là tất cả các số đều có một dấu hiệu ngầm gắn liền với chúng cho dù bạn có chỉ định hay không. Điều này cho thấy khi bạn thực hiện KHÔNG theo chiều bit của bất kỳ số nào

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
93

Thay vì 9910 như mong đợi, bạn nhận được giá trị âm. Lý do cho điều này sẽ trở nên rõ ràng khi bạn tìm hiểu về các. Hiện tại, giải pháp khắc phục nhanh là tận dụng toán tử AND theo bit

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
94

Đó là một ví dụ hoàn hảo về , mà bạn sẽ khám phá ở một trong những phần sắp tới

Loại bỏ các quảng cáo

Toán tử dịch chuyển theo bit

Toán tử dịch chuyển bit là một loại công cụ khác để thao tác bit. Chúng cho phép bạn di chuyển các bit xung quanh, điều này sẽ hữu ích cho việc tạo các mặt nạ bit sau này. Trước đây, chúng thường được sử dụng để cải thiện tốc độ của một số phép toán nhất định

Dịch trái

Toán tử dịch trái theo chiều bit [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
9] di chuyển các bit của toán hạng thứ nhất sang trái theo số vị trí được chỉ định trong toán hạng thứ hai của nó. Nó cũng quan tâm đến việc chèn đủ bit 0 để lấp đầy khoảng trống phát sinh ở cạnh phải của mẫu bit mới

Dịch chuyển một bit sang trái một vị trí sẽ nhân đôi giá trị của nó. Ví dụ: thay vì số hai, bit sẽ chỉ số bốn sau khi dịch chuyển. Di chuyển nó sang bên trái hai vị trí sẽ tăng gấp bốn lần giá trị kết quả. Khi bạn cộng tất cả các bit thành một số nhất định, bạn sẽ nhận thấy rằng nó cũng được nhân đôi với mỗi vị trí được thay đổi

Biểu thức Giá trị nhị phân Giá trị thập phân ____193110011123910

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
948100111027810
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
94910011100215610
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
950100111000231210

Nói chung, dịch chuyển các bit sang trái tương ứng với việc nhân một số với lũy thừa hai, với số mũ bằng với số vị trí được dịch chuyển

Dịch trái từng là một kỹ thuật tối ưu hóa phổ biến vì dịch chuyển bit là một lệnh đơn lẻ và tính toán rẻ hơn so với số mũ hoặc tích. Tuy nhiên, ngày nay, các trình biên dịch và trình thông dịch, bao gồm cả Python, hoàn toàn có khả năng tối ưu hóa mã của bạn đằng sau hậu trường

Ghi chú. Không sử dụng toán tử dịch chuyển bit làm phương tiện tối ưu hóa sớm trong Python. Bạn sẽ không thấy sự khác biệt về tốc độ thực thi, nhưng chắc chắn bạn sẽ làm cho mã của mình khó đọc hơn

Trên giấy, mẫu bit do dịch chuyển trái sẽ dài hơn ở nhiều vị trí khi bạn dịch chuyển nó. Điều đó cũng đúng với Python nói chung vì cách nó xử lý các số nguyên. Tuy nhiên, trong hầu hết các trường hợp thực tế, bạn sẽ muốn hạn chế độ dài của mẫu bit là bội số của tám, là độ dài byte tiêu chuẩn

Ví dụ: nếu bạn đang làm việc với một byte đơn, thì việc dịch chuyển nó sang bên trái sẽ loại bỏ tất cả các bit vượt ra ngoài ranh giới bên trái của nó

Nó giống như nhìn vào một luồng bit không giới hạn thông qua một cửa sổ có độ dài cố định. Có một vài thủ thuật cho phép bạn làm điều này trong Python. Ví dụ: bạn có thể áp dụng a với toán tử AND theo bit

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
95

Dịch chuyển 3910 ba vị trí sang trái sẽ trả về một số cao hơn giá trị tối đa mà bạn có thể lưu trữ trên một byte đơn. Phải mất chín bit, trong khi một byte chỉ có tám. Để cắt bớt một bit thừa ở bên trái, bạn có thể áp dụng một bitmask với giá trị phù hợp. Nếu bạn muốn giữ nhiều hoặc ít bit hơn, thì bạn sẽ cần sửa đổi giá trị mặt nạ cho phù hợp

Ca phải

Toán tử dịch phải theo chiều bit [

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
901] tương tự như toán tử bên trái, nhưng thay vì di chuyển các bit sang trái, nó đẩy chúng sang phải theo số vị trí đã chỉ định. Các bit ngoài cùng bên phải luôn bị loại bỏ

Mỗi khi bạn dịch chuyển một chút sang phải một vị trí, bạn sẽ giảm một nửa giá trị cơ bản của nó. Di chuyển cùng một bit sang bên phải hai vị trí sẽ tạo ra một phần tư giá trị ban đầu, v.v. Khi bạn cộng tất cả các bit riêng lẻ, bạn sẽ thấy quy tắc tương tự áp dụng cho số mà chúng đại diện

Biểu thức Giá trị nhị phân Giá trị thập phân ____193110011101215710

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
953100111027810
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
95410011123910
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
9551001121910

Giảm một nửa số lẻ chẳng hạn như 15710 sẽ tạo ra một phân số. Để thoát khỏi nó, toán tử shift phải sẽ tự động kết quả. Nó hầu như giống như phép chia tầng bằng lũy ​​thừa hai

Một lần nữa, số mũ tương ứng với số lượng vị trí dịch chuyển sang phải. Trong Python, bạn có thể tận dụng một toán tử chuyên dụng để thực hiện phân chia tầng

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
96

Cả toán tử dịch chuyển phải theo chiều bit và toán tử chia tầng đều hoạt động theo cùng một cách, ngay cả đối với các số âm. Tuy nhiên, phép chia sàn cho phép bạn chọn bất kỳ ước số nào và không chỉ là lũy thừa của hai. Sử dụng dịch chuyển phải theo chiều bit là một cách phổ biến để cải thiện hiệu suất của một số phép chia số học

Ghi chú. Bạn có thể tự hỏi điều gì sẽ xảy ra khi bạn hết bit để chuyển. Ví dụ: khi bạn thử đẩy nhiều vị trí hơn số bit trong một số

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
97

Khi không còn bit nào được bật, bạn sẽ bị mắc kẹt với giá trị bằng 0. Số không chia cho bất cứ thứ gì sẽ luôn trả về số không. Tuy nhiên, mọi thứ trở nên phức tạp hơn khi bạn chuyển sang phải một số âm vì bit dấu ẩn cản trở

>>>

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
98

Quy tắc ngón tay cái là, bất kể dấu hiệu là gì, kết quả sẽ giống như phép chia sàn cho một số lũy thừa của hai. Sàn của một phân số âm nhỏ luôn là trừ một, và đó là những gì bạn sẽ nhận được. Đọc tiếp để được giải thích chi tiết hơn

Cũng giống như toán tử dịch trái, mẫu bit thay đổi kích thước của nó sau khi dịch phải. Mặc dù di chuyển các bit sang bên phải làm cho chuỗi nhị phân ngắn hơn, nhưng điều đó thường không thành vấn đề vì bạn có thể đặt bao nhiêu số 0 trước chuỗi bit tùy thích mà không thay đổi giá trị. Ví dụ: 1012 giống như 01012 và 000001012 cũng vậy, miễn là bạn đang xử lý các số không âm

Đôi khi, bạn sẽ muốn giữ một độ dài bit nhất định sau khi thực hiện dịch chuyển sang phải để căn chỉnh nó với một giá trị khác hoặc để khớp với một nơi nào đó. Bạn có thể làm điều đó bằng cách áp dụng một bitmask

Nó chỉ cắt ra những bit mà bạn quan tâm và điền vào mẫu bit với các số 0 đứng đầu nếu cần

Việc xử lý các số âm trong Python hơi khác so với cách tiếp cận truyền thống để dịch chuyển bit. Trong phần tiếp theo, bạn sẽ kiểm tra điều này chi tiết hơn

Loại bỏ các quảng cáo

Số học vs Dịch chuyển logic

Bạn có thể phân loại thêm các toán tử dịch chuyển bit thành toán tử dịch chuyển số học và logic. Mặc dù Python chỉ cho phép bạn thực hiện phép dịch chuyển số học, nhưng bạn nên biết cách các ngôn ngữ lập trình khác triển khai các toán tử dịch chuyển bit để tránh nhầm lẫn và bất ngờ

Sự khác biệt này xuất phát từ cách chúng xử lý bit dấu, thường nằm ở cạnh ngoài cùng bên trái của chuỗi nhị phân có dấu. Trong thực tế, nó chỉ liên quan đến toán tử dịch chuyển phải, điều này có thể khiến một số bị đảo dấu, dẫn đến tràn số nguyên

Ghi chú. Ví dụ, Java và JavaScript phân biệt toán tử dịch phải logic bằng một dấu lớn hơn bổ sung [

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
903]. Vì toán tử dịch chuyển trái hoạt động nhất quán trên cả hai loại ca, nên các ngôn ngữ này không xác định đối chiếu dịch trái hợp lý

Thông thường, một bit dấu bật cho biết các số âm, giúp giữ các thuộc tính số học của một chuỗi nhị phân

Giá trị thập phân Giá trị nhị phân đã kýSign BitSignMeaning-100101001110021-Số âm28100001110020+Số dương hoặc số không

Nhìn từ bên trái vào hai dãy nhị phân này, bạn có thể thấy rằng bit đầu tiên của chúng mang thông tin về dấu hiệu, trong khi phần còn lại bao gồm các bit độ lớn, giống nhau cho cả hai số

Ghi chú. Các giá trị thập phân cụ thể sẽ phụ thuộc vào cách bạn quyết định biểu thị các số có dấu ở dạng nhị phân. Nó khác nhau giữa các ngôn ngữ và thậm chí còn phức tạp hơn trong Python, vì vậy bạn có thể tạm thời bỏ qua nó. Bạn sẽ có một bức tranh đẹp hơn khi bạn đến phần bên dưới

Dịch chuyển phải hợp lý, còn được gọi là dịch chuyển phải không dấu hoặc dịch chuyển phải không điền, di chuyển toàn bộ chuỗi nhị phân, bao gồm cả bit dấu và lấp đầy khoảng trống kết quả ở bên trái bằng các số không

Chú ý thông tin về dấu của số bị mất. Bất kể dấu ban đầu là gì, nó sẽ luôn tạo ra một số nguyên không âm vì bit dấu được thay thế bằng 0. Miễn là bạn không quan tâm đến các giá trị số, thì một phép dịch phải hợp lý có thể hữu ích trong việc xử lý dữ liệu nhị phân cấp thấp

Tuy nhiên, vì các số nhị phân có dấu thường được lưu trữ trên một chuỗi bit có độ dài cố định trong hầu hết các ngôn ngữ nên nó có thể làm cho kết quả bao quanh các giá trị cực đoan. Bạn có thể thấy điều này trong công cụ Java Shell tương tác

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
99

Số kết quả thay đổi dấu của nó từ âm sang dương, nhưng nó cũng bị tràn, kết thúc rất gần với số nguyên tối đa của Java

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
30

Con số này thoạt nhìn có vẻ tùy ý, nhưng nó liên quan trực tiếp đến số lượng bit mà Java phân bổ cho kiểu dữ liệu

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
957

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
31

Nó sử dụng 32 bit để lưu trữ trong biểu diễn bù hai. Khi bạn lấy bit dấu ra, bạn còn lại 31 bit, có giá trị thập phân tối đa bằng 231 - 1 hoặc 214748364710

Mặt khác, Python lưu trữ các số nguyên như thể có vô số bit theo ý của bạn. Do đó, một toán tử dịch phải hợp lý sẽ không được xác định rõ trong Python thuần túy, do đó, nó bị thiếu trong ngôn ngữ. Tuy nhiên, bạn vẫn có thể mô phỏng nó

Một cách để làm như vậy là tận dụng các kiểu dữ liệu không dấu có sẵn trong C được hiển thị thông qua mô-đun

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
958 tích hợp sẵn

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
32

Họ cho phép bạn nhập một số âm nhưng không gắn bất kỳ ý nghĩa đặc biệt nào với bit dấu. Nó được xử lý giống như phần còn lại của các bit cường độ

Mặc dù chỉ có một số loại số nguyên không dấu được xác định trước trong C, khác nhau về độ dài bit, nhưng bạn có thể tạo một hàm tùy chỉnh trong Python để xử lý các độ dài bit tùy ý

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
33

Thao tác này chuyển đổi chuỗi bit có dấu thành chuỗi không dấu và sau đó thực hiện phép dịch phải số học thông thường

Tuy nhiên, vì các chuỗi bit trong Python không cố định về độ dài nên chúng không thực sự có bit dấu. Hơn nữa, chúng không sử dụng biểu diễn bù hai truyền thống như trong C hoặc Java. Để giảm thiểu điều đó, bạn có thể tận dụng thao tác modulo, thao tác này sẽ giữ nguyên các mẫu bit ban đầu cho các số nguyên dương trong khi bao quanh các số nguyên âm một cách thích hợp

Phép dịch phải số học [

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
901], đôi khi được gọi là toán tử dịch phải có dấu, duy trì dấu của một số bằng cách sao chép bit dấu của nó trước khi di chuyển các bit sang phải

Nói cách khác, nó lấp đầy khoảng trống ở bên trái bằng bất kỳ bit dấu nào. Kết hợp với biểu diễn bổ sung của hai nhị phân đã ký, điều này dẫn đến một giá trị chính xác về mặt số học. Bất kể số đó là dương hay âm, một phép dịch phải số học tương đương với phép chia sàn

Như bạn sắp tìm hiểu, Python không phải lúc nào cũng lưu trữ các số nguyên ở dạng nhị phân bù hai đơn giản. Thay vào đó, nó tuân theo một chiến lược thích ứng tùy chỉnh hoạt động giống như với số lượng bit không giới hạn. Nó chuyển đổi các số qua lại giữa biểu diễn bên trong của chúng và phần bù hai để bắt chước hành vi tiêu chuẩn của phép dịch số học

Loại bỏ các quảng cáo

Đại diện số nhị phân

Bạn đã trực tiếp trải nghiệm việc thiếu các kiểu dữ liệu không dấu trong Python khi sử dụng phủ định bitwise [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
7] và toán tử shift phải [
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
901]. Bạn đã thấy các gợi ý về cách tiếp cận bất thường để lưu trữ , khiến việc xử lý các số âm trở nên khó khăn. Để sử dụng các toán tử bitwise một cách hiệu quả, bạn cần biết về các cách biểu diễn khác nhau của các số trong hệ nhị phân

Số nguyên không dấu

Trong các ngôn ngữ lập trình như C, bạn chọn sử dụng kiểu có dấu hoặc không dấu của một loại số nhất định. Các kiểu dữ liệu không dấu sẽ phù hợp hơn khi bạn biết chắc rằng mình sẽ không bao giờ phải xử lý các số âm. Bằng cách phân bổ một bit bổ sung đó, nếu không sẽ đóng vai trò là bit dấu, bạn thực tế đã nhân đôi phạm vi giá trị khả dụng

Nó cũng làm cho mọi thứ an toàn hơn một chút bằng cách tăng giới hạn tối đa trước khi tràn xảy ra. Tuy nhiên, tràn chỉ xảy ra với độ dài bit cố định, vì vậy chúng không liên quan đến Python, vốn không có các ràng buộc như vậy

Cách nhanh nhất để tìm hiểu về các kiểu số không dấu trong Python là sử dụng mô-đun

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
958 đã đề cập trước đó

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
34

Vì không có bit dấu trong các số nguyên như vậy nên tất cả các bit của chúng biểu thị độ lớn của một số. Việc truyền một số âm buộc Python phải diễn giải lại mẫu bit như thể nó chỉ có các bit cường độ

Số nguyên có dấu

Dấu của một số chỉ có hai trạng thái. Nếu bạn bỏ qua số 0 trong giây lát, thì nó có thể dương hoặc âm, điều này chuyển thành hệ thống nhị phân một cách độc đáo. Tuy nhiên, có một số cách khác để biểu diễn các số nguyên đã ký ở dạng nhị phân, mỗi cách đều có ưu và nhược điểm riêng.

Có lẽ cách đơn giản nhất là độ lớn của dấu, được xây dựng một cách tự nhiên trên các số nguyên không dấu. Khi một chuỗi nhị phân được hiểu là độ lớn dấu, nó đóng vai trò của một bit dấu, trong khi các bit còn lại hoạt động giống như bình thường

Chuỗi nhị phân Giá trị độ lớn ký Giá trị không dấu00101010242104210101010102-421017010

Số 0 ở bit ngoài cùng bên trái biểu thị số dương [________ 1963] và số 1 biểu thị số âm [________ 1964]. Lưu ý rằng một bit dấu không đóng góp vào giá trị tuyệt đối của số trong biểu diễn cường độ dấu. Nó chỉ ở đó để cho phép bạn lật dấu của các bit còn lại

Tại sao bit ngoài cùng bên trái?

Nó giữ nguyên chỉ mục bit, do đó, giúp duy trì khả năng tương thích ngược của trọng số bit được sử dụng để tính giá trị thập phân của chuỗi nhị phân. Tuy nhiên, không phải mọi thứ về độ lớn của dấu hiệu đều tuyệt vời như vậy

Ghi chú. Các biểu diễn nhị phân của các số nguyên đã ký chỉ có ý nghĩa đối với các chuỗi bit có độ dài cố định. Mặt khác, bạn không thể biết vị trí của bit dấu. Tuy nhiên, trong Python, bạn có thể biểu diễn số nguyên bằng bao nhiêu bit tùy thích

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
35

Cho dù đó là bốn bit hay tám bit, bit dấu sẽ luôn được tìm thấy ở vị trí ngoài cùng bên trái

Phạm vi giá trị mà bạn có thể lưu trữ trong mẫu bit biên độ ký hiệu là đối xứng. Nhưng điều đó cũng có nghĩa là bạn sẽ có hai cách để truyền đạt số không

Chuỗi nhị phân Giá trị độ lớn ký Giá trị không dấu000000002+010010100000002-01012810

Về mặt kỹ thuật, số 0 không có ký hiệu, nhưng không có cách nào để không bao gồm một ký hiệu trong cường độ ký hiệu. Mặc dù có một số 0 mơ hồ không phải là lý tưởng trong hầu hết các trường hợp, nhưng đó không phải là phần tồi tệ nhất của câu chuyện. Nhược điểm lớn nhất của phương pháp này là số học nhị phân cồng kềnh

Khi bạn áp dụng số học nhị phân tiêu chuẩn cho các số được lưu trữ ở ký hiệu, nó có thể không mang lại cho bạn kết quả như mong đợi. Ví dụ: cộng hai số có cùng độ lớn nhưng ngược dấu sẽ không làm cho chúng bị triệt tiêu

Biểu thức Chuỗi nhị phân Giá trị ký-độ lớn

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
9310010101024210
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
932101010102-4210
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
967110101002-8410

Tổng của 42 và -42 không tạo ra số 0. Ngoài ra, bit chuyển đổi đôi khi có thể truyền từ độ lớn sang bit dấu, đảo ngược dấu hiệu và mang lại kết quả không mong muốn

Để giải quyết những vấn đề này, một số máy tính đời đầu đã sử dụng biểu diễn bổ sung của một người. Ý tưởng là thay đổi cách các số thập phân được ánh xạ tới các chuỗi nhị phân cụ thể để chúng có thể được cộng lại một cách chính xác. Để tìm hiểu sâu hơn về phần bổ sung của một người, bạn có thể mở rộng phần bên dưới

Phần bù của một ngườiHiển thị/Ẩn

Trong phần bù của một số, các số dương giống như trong độ lớn của dấu hiệu, nhưng các số âm có được bằng cách lật các bit của số dương bằng cách sử dụng một bit NOT

Dãy dương Dãy âm Giá trị độ lớn000000002111111112±010000000012111111102±110000000102111111012±210⋮⋮⋮011111112100000002±12710

Điều này giữ nguyên ý nghĩa ban đầu của bit dấu, vì vậy các số dương vẫn bắt đầu bằng số 0 nhị phân, trong khi số âm bắt đầu bằng số nhị phân. Tương tự như vậy, phạm vi của các giá trị vẫn đối xứng và tiếp tục có hai cách biểu thị số không. Tuy nhiên, chuỗi nhị phân của các số âm trong phần bù của một người được sắp xếp theo thứ tự ngược lại so với độ lớn của dấu

Một số bổ sung-magnitudedecimal value111111112100000002-010111111102100000012-110111111012100000102-210

Nhờ đó, giờ đây bạn có thể cộng hai số một cách đáng tin cậy hơn vì bit dấu không cần xử lý đặc biệt. Nếu một chuyển đổi bắt nguồn từ bit dấu, nó sẽ được đưa trở lại ở cạnh phải của chuỗi nhị phân thay vì chỉ bị loại bỏ. Điều này đảm bảo kết quả chính xác

Tuy nhiên, các máy tính hiện đại không sử dụng phần bù một để biểu diễn các số nguyên vì có một cách thậm chí còn tốt hơn được gọi là phần bù hai. Bằng cách áp dụng một sửa đổi nhỏ, bạn có thể loại bỏ hai số 0 và đơn giản hóa số học nhị phân trong một lần. Để khám phá phần bù của hai chi tiết hơn, bạn có thể mở rộng phần bên dưới

Phần bù của haiHiển thị/Ẩn

Khi tìm các chuỗi bit có giá trị âm trong phần bù hai, mẹo là thêm một vào kết quả sau khi phủ định các bit

Dãy dươngSố bù một [NOT]Số bù hai [NOT+1]000000002111111112000000002000000012111111102111111112000000102111110121111111102⋮⋮⋮0111110001000

Điều này đẩy chuỗi bit của các số âm xuống một vị trí, loại bỏ dấu trừ 0 khét tiếng. Thay vào đó, một dấu trừ hữu ích hơn sẽ chiếm lấy mẫu bit của nó

Là một tác dụng phụ, phạm vi các giá trị có sẵn trong phần bù của hai trở nên không đối xứng, với giới hạn dưới là lũy thừa của hai và giới hạn trên là số lẻ. Ví dụ: số nguyên có dấu 8 bit sẽ cho phép bạn lưu trữ các số từ -12810 đến 12710 trong phần bù hai

Hai bổ sung bổ sung Giá trị bổ sung100000002N/A-12810100000012100000002-12710100000102100000012-12610

Một cách khác để nói rằng bit quan trọng nhất mang cả dấu và một phần của độ lớn số

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3Bit 2Bit 1Bit 0-2726252423222120-1286432168421

Lưu ý dấu trừ bên cạnh trọng lượng bit ngoài cùng bên trái. Lấy một giá trị thập phân từ một chuỗi nhị phân như thế chỉ là vấn đề thêm các cột thích hợp. Ví dụ: giá trị của 110101102 trong biểu diễn bù hai 8 bit giống với tổng. -12810 + 6410 + 1610 + 410 + 210 = -4210

Với biểu diễn bổ sung của cả hai, bạn không còn phải lo lắng về bit chuyển tiếp trừ khi bạn muốn sử dụng nó như một cơ chế phát hiện tràn, điều này khá gọn gàng.

Có một số biến thể khác của biểu diễn số có dấu, nhưng chúng không phổ biến bằng

Loại bỏ các quảng cáo

Số dấu phẩy động

Tiêu chuẩn IEEE 754 xác định biểu diễn nhị phân cho các số thực bao gồm các bit dấu, số mũ và phần định trị. Không đi sâu vào quá nhiều chi tiết kỹ thuật, bạn có thể coi nó như một ký hiệu khoa học cho các số nhị phân. Dấu thập phân "trôi" xung quanh để chứa một số lượng khác nhau của các số liệu quan trọng, ngoại trừ đó là một điểm nhị phân

Hai loại dữ liệu phù hợp với tiêu chuẩn đó được hỗ trợ rộng rãi

  1. Độ chính xác đơn. 1 bit dấu, 8 bit số mũ, 23 bit định trị
  2. Độ chính xác gấp đôi. 1 bit dấu, 11 bit số mũ, 52 bit định trị

Kiểu dữ liệu

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
968 của Python tương đương với kiểu chính xác kép. Lưu ý rằng một số ứng dụng yêu cầu nhiều hoặc ít bit hơn. Ví dụ: định dạng hình ảnh OpenEXR tận dụng độ chính xác một nửa để biểu thị các pixel có dải màu động cao ở kích thước tệp hợp lý

Số Pi [π] có biểu diễn nhị phân sau với độ chính xác duy nhất khi được làm tròn đến năm chữ số thập phân

Ký số mũMantissa02100000002. 100100100001111110100002

Bit dấu hoạt động giống như với số nguyên, vì vậy số 0 biểu thị số dương. Tuy nhiên, đối với số mũ và phần định trị, các quy tắc khác nhau có thể áp dụng tùy thuộc vào một số trường hợp cạnh

Trước tiên, bạn cần chuyển đổi chúng từ dạng nhị phân sang dạng thập phân

  • số mũ. 12810
  • bọ ngựa. 2-1 + 2-4 + … + 2-19 = 29926110/52428810 ≈ 0. 57079510

Số mũ được lưu dưới dạng số nguyên không dấu, nhưng để tính các giá trị âm, nó thường có độ lệch bằng 12710 với độ chính xác đơn. Bạn cần trừ nó để khôi phục số mũ thực tế

Các bit định trị đại diện cho một phân số, vì vậy chúng tương ứng với các lũy thừa âm của hai. Ngoài ra, bạn cần thêm một vào phần định trị vì nó giả định một bit dẫn trước ẩn trước điểm cơ số trong trường hợp cụ thể này

Đặt tất cả lại với nhau, bạn đi đến công thức sau để chuyển đổi số nhị phân dấu phẩy động thành số thập phân

Khi bạn thay thế các biến cho các giá trị thực tế trong ví dụ trên, bạn sẽ có thể giải mã mẫu bit của một số dấu phẩy động được lưu trữ với độ chính xác đơn

Đây rồi, miễn là Pi đã được làm tròn đến năm chữ số thập phân. Bạn sẽ học cách làm sau này

Số điểm cố định

Mặc dù các số dấu phẩy động rất phù hợp cho các mục đích kỹ thuật, nhưng chúng không thành công trong tính toán tiền tệ do độ chính xác hạn chế của chúng. Ví dụ: một số số có biểu diễn hữu hạn trong ký hiệu thập phân chỉ có biểu diễn vô hạn trong hệ nhị phân. Điều đó thường dẫn đến lỗi làm tròn, có thể tích lũy theo thời gian

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
36

Trong những trường hợp như vậy, tốt hơn hết bạn nên sử dụng mô-đun của Python, mô-đun này triển khai số học điểm cố định và cho phép bạn chỉ định vị trí đặt dấu thập phân trên một độ dài bit nhất định. Ví dụ: bạn có thể cho biết bạn muốn giữ nguyên bao nhiêu chữ số

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
37

Tuy nhiên, nó bao gồm tất cả các chữ số, không chỉ các phân số

Ghi chú. Nếu bạn đang làm việc với các số hữu tỷ, thì bạn có thể quan tâm đến việc kiểm tra mô-đun

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
970, đây là một phần của thư viện chuẩn của Python

Nếu bạn không thể hoặc không muốn sử dụng loại dữ liệu điểm cố định, thì một cách đơn giản để lưu trữ giá trị tiền tệ một cách đáng tin cậy là chia tỷ lệ số tiền thành đơn vị nhỏ nhất, chẳng hạn như xu và biểu thị chúng bằng số nguyên

Loại bỏ các quảng cáo

Số nguyên trong Python

Ngày xưa của lập trình, bộ nhớ máy tính rất cao. Do đó, các ngôn ngữ sẽ cung cấp cho bạn quyền kiểm soát khá chi tiết về số lượng byte cần phân bổ cho dữ liệu của bạn. Hãy xem nhanh một vài kiểu số nguyên từ C làm ví dụ

LoạiKích thướcGiá trị tối thiểuGiá trị tối đa

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
9711 byte-128127
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
9722 byte-32,76832,767
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
9734 byte-2,147,483,6482,147,483,647
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
9748 byte-9,223,372,036,854,775,8089,248,703,703,3

Các giá trị này có thể thay đổi từ nền tảng này sang nền tảng khác. Tuy nhiên, sự phong phú của các loại số như vậy cho phép bạn sắp xếp dữ liệu trong bộ nhớ một cách gọn gàng. Hãy nhớ rằng những thứ này thậm chí không bao gồm các loại không dấu

Ở phía bên kia của quang phổ là các ngôn ngữ như JavaScript, chỉ có một loại số để cai trị tất cả chúng. Mặc dù điều này ít gây nhầm lẫn hơn đối với những người mới bắt đầu lập trình, nhưng nó phải trả giá bằng việc tăng mức tiêu thụ bộ nhớ, giảm hiệu quả xử lý và giảm độ chính xác

Khi nói về các toán tử bitwise, điều cần thiết là phải hiểu cách Python xử lý các số nguyên. Rốt cuộc, bạn sẽ chủ yếu sử dụng các toán tử này để làm việc với các số nguyên. Có một vài cách biểu diễn số nguyên cực kỳ khác nhau trong Python phụ thuộc vào giá trị của chúng

số nguyên nội suy

Trong CPython, các số nguyên rất nhỏ trong khoảng từ -510 đến 25610 nằm trong bộ đệm chung để đạt được một số hiệu suất vì các số trong phạm vi đó thường được sử dụng. Trong thực tế, bất cứ khi nào bạn đề cập đến một trong những giá trị đó, là những giá trị đơn lẻ được tạo khi khởi động trình thông dịch, Python sẽ luôn cung cấp cùng một phiên bản

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
38

Cả hai biến đều giống nhau vì chúng đề cập đến cùng một đối tượng trong bộ nhớ. Đó là điển hình của các loại tham chiếu nhưng không phải là giá trị bất biến, chẳng hạn như số nguyên. Tuy nhiên, khi bạn vượt ra ngoài phạm vi giá trị được lưu trong bộ nhớ cache đó, Python sẽ bắt đầu tạo các bản sao riêng biệt trong quá trình gán biến

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
39

Mặc dù có các giá trị bằng nhau, các biến này hiện đang trỏ đến các đối tượng riêng biệt. Nhưng đừng để điều đó đánh lừa bạn. Python sẽ thỉnh thoảng nhảy vào và tối ưu hóa mã của bạn ở hậu trường. Ví dụ: nó sẽ lưu vào bộ đệm một số xuất hiện trên cùng một dòng nhiều lần bất kể giá trị của nó là gì

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
70

Các biến

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
931 và
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
932 là các đối tượng độc lập vì chúng nằm ở các vị trí bộ nhớ khác nhau, trong khi các số được sử dụng theo nghĩa đen trong
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
977 thực tế là cùng một đối tượng

Ghi chú. Thực tập là một chi tiết triển khai của trình thông dịch CPython, có thể thay đổi trong các phiên bản sau, vì vậy đừng dựa vào nó trong các chương trình của bạn

Thật thú vị, có một cơ chế thực tập chuỗi tương tự trong Python, khởi động cho các văn bản ngắn chỉ bao gồm các chữ cái ASCII. Nó giúp tăng tốc độ tra cứu từ điển bằng cách cho phép so sánh các khóa của chúng theo địa chỉ bộ nhớ hoặc con trỏ C, thay vì theo từng ký tự chuỗi riêng lẻ

Số nguyên có độ chính xác cố định

Các số nguyên mà bạn có nhiều khả năng tìm thấy nhất trong Python sẽ tận dụng kiểu dữ liệu C

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
978. Họ sử dụng biểu diễn nhị phân bổ sung của hai cổ điển trên một số bit cố định. Độ dài bit chính xác sẽ phụ thuộc vào nền tảng phần cứng, hệ điều hành và phiên bản trình thông dịch Python của bạn

Các máy tính hiện đại thường sử dụng kiến ​​trúc 64-bit, vì vậy điều này sẽ chuyển thành số thập phân giữa -263 và 263 - 1. Bạn có thể kiểm tra giá trị lớn nhất của số nguyên có độ chính xác cố định trong Python theo cách sau

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
71

Nó rất lớn. Khoảng 9 triệu lần số lượng các ngôi sao trong thiên hà của chúng ta, vì vậy nó đủ để sử dụng hàng ngày. Mặc dù giá trị tối đa mà bạn có thể vắt ra từ loại

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
979 trong C thậm chí còn lớn hơn, theo thứ tự 1019, các số nguyên trong Python không có giới hạn về mặt lý thuyết. Để cho phép điều này, các số không phù hợp với chuỗi bit có độ dài cố định được lưu trữ khác nhau trong bộ nhớ

Loại bỏ các quảng cáo

Số nguyên chính xác tùy ý

Bạn có nhớ bài hát K-pop nổi tiếng “Gangnam Style” đã trở thành hit trên toàn thế giới vào năm 2012 không? . Ngay sau đó, rất nhiều người đã xem video khiến bộ đếm lượt xem tràn ngập. YouTube không có lựa chọn nào khác ngoài việc nâng cấp bộ đếm của họ từ số nguyên có chữ ký 32 bit lên số nguyên 64 bit

Điều đó có thể mang lại nhiều khoảng trống cho quầy xem, nhưng thậm chí còn có những con số lớn hơn không phải là hiếm trong cuộc sống thực, đặc biệt là trong thế giới khoa học. Tuy nhiên, Python có thể xử lý chúng một cách dễ dàng

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
72

Số này có năm mươi hai chữ số thập phân. Sẽ mất ít nhất 170 bit để biểu diễn nó ở dạng nhị phân với cách tiếp cận truyền thống

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
73

Vì chúng vượt quá giới hạn mà bất kỳ loại C nào cũng phải cung cấp, nên các số thiên văn như vậy được chuyển đổi thành một hệ thống vị trí có độ lớn ký hiệu, có cơ sở là 230. Vâng, bạn đã đọc dúng điều đó. Trong khi bạn có mười ngón tay, Python có hơn một tỷ

Một lần nữa, điều này có thể khác nhau tùy thuộc vào nền tảng bạn hiện đang sử dụng. Khi nghi ngờ, bạn có thể kiểm tra lại

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
74

Điều này sẽ cho bạn biết có bao nhiêu bit được sử dụng trên mỗi chữ số và kích thước tính bằng byte của cấu trúc C bên dưới. Để có được điều tương tự trong Python 2, thay vào đó, bạn nên tham khảo thuộc tính

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
980

Mặc dù việc chuyển đổi này giữa các số nguyên có độ chính xác cố định và độ chính xác tùy ý được thực hiện liền mạch trong Python 3, nhưng đã có lúc mọi thứ trở nên rõ ràng hơn. Để biết thêm thông tin, bạn có thể mở rộng hộp bên dưới

______1973 và

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
974 bằng Python 2Hiển thị/Ẩn

Trước đây, Python đã định nghĩa rõ ràng hai loại số nguyên riêng biệt

  1. số nguyên đơn giản
  2. Số nguyên dài

Loại đầu tiên được mô phỏng theo loại C

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
978, thường chiếm 32 hoặc 64 bit và cung cấp một phạm vi giá trị hạn chế

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
75

Đối với số lượng lớn hơn, bạn phải sử dụng loại thứ hai không có giới hạn. Python sẽ tự động thăng cấp số nguyên đơn giản thành số nguyên dài nếu cần

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
76

Tính năng này đã ngăn chặn lỗi tràn số nguyên. Lưu ý chữ cái

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
984 ở cuối một chữ cái, có thể được sử dụng để thực thi loại đã cho bằng tay

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
77

Cuối cùng, cả hai loại đã được thống nhất để bạn không phải suy nghĩ về nó nữa

Cách biểu diễn như vậy giúp loại bỏ các lỗi tràn số nguyên và tạo ảo giác về độ dài bit vô hạn, nhưng nó đòi hỏi nhiều bộ nhớ hơn. Ngoài ra, việc thực hiện số học bignum chậm hơn so với với độ chính xác cố định vì nó không thể chạy trực tiếp trong phần cứng mà không có lớp mô phỏng trung gian

Một thách thức khác là giữ hành vi nhất quán của các toán tử bit trên các loại số nguyên thay thế, điều này rất quan trọng trong việc xử lý bit dấu. Nhớ lại rằng các số nguyên có độ chính xác cố định trong Python sử dụng biểu diễn phần bù của hai tiêu chuẩn từ C, trong khi các số nguyên lớn sử dụng độ lớn ký hiệu

Để giảm thiểu sự khác biệt đó, Python sẽ thực hiện chuyển đổi nhị phân cần thiết cho bạn. Nó có thể thay đổi cách biểu diễn một số trước và sau khi áp dụng toán tử bitwise. Đây là một nhận xét có liên quan từ mã nguồn CPython, giải thích điều này chi tiết hơn

Các phép toán theo bit cho các số âm hoạt động như thể trên biểu diễn phần bù của hai. Vì vậy, hãy chuyển đổi các đối số từ độ lớn của dấu hiệu thành phần bù của hai và chuyển đổi kết quả trở lại độ lớn của dấu hiệu ở cuối. []

Nói cách khác, các số âm được coi là chuỗi bit bổ sung của hai khi bạn áp dụng toán tử bitwise trên chúng, mặc dù kết quả sẽ được hiển thị cho bạn ở dạng ký hiệu. Tuy nhiên, có nhiều cách và một số loại không dấu trong Python

Chuỗi bit trong Python

Bạn có thể sử dụng bút và giấy trong suốt phần còn lại của bài viết này. Nó thậm chí có thể phục vụ như một bài tập tuyệt vời. Tuy nhiên, tại một số điểm, bạn sẽ muốn xác minh xem các chuỗi nhị phân hoặc chuỗi bit của mình có tương ứng với các số dự kiến ​​trong Python hay không. Đây là cách

Chuyển đổi
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
973 sang nhị phân

Để hiển thị các bit tạo thành một số nguyên trong Python, bạn có thể in một chuỗi ký tự được định dạng, tùy chọn này cho phép bạn chỉ định số lượng các số 0 đứng đầu sẽ hiển thị

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
78

Ngoài ra, bạn có thể gọi

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
986 với số làm đối số

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
79

Hàm tích hợp toàn cục này trả về một chuỗi bao gồm một ký tự nhị phân, bắt đầu bằng tiền tố

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
987 và theo sau là các số 1 và 0. Nó luôn hiển thị số chữ số tối thiểu không có số 0 đứng đầu

Bạn cũng có thể sử dụng nguyên văn các từ như vậy trong mã của mình

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
10

Các ký tự số nguyên khác có sẵn trong Python là các ký tự thập lục phân và bát phân, mà bạn có thể nhận được bằng các hàm

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
988 và
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
989, tương ứng

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
11

Lưu ý cách hệ thập lục phân, cơ số mười sáu, tận dụng các chữ cái từ

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
990 đến
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
991 để tăng thêm tập hợp các chữ số có sẵn. Các ký tự bát phân trong các ngôn ngữ lập trình khác thường có tiền tố là số 0, điều này có thể gây nhầm lẫn. Python rõ ràng cấm những chữ như vậy để tránh mắc lỗi

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
12

Bạn có thể biểu thị cùng một giá trị theo nhiều cách khác nhau bằng cách sử dụng bất kỳ số nguyên nào được đề cập

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
13

Chọn cái có ý nghĩa nhất trong ngữ cảnh. Ví dụ: theo thông lệ, biểu thị bằng ký hiệu thập lục phân. Mặt khác, chữ bát phân ngày nay hiếm khi được nhìn thấy

Tất cả các chữ số trong Python đều không phân biệt chữ hoa chữ thường, vì vậy bạn có thể thêm tiền tố cho chúng bằng chữ thường hoặc chữ hoa

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
14

Điều này cũng áp dụng cho các chữ số dấu phẩy động sử dụng ký hiệu khoa học cũng như các chữ số phức tạp.

Loại bỏ các quảng cáo

Chuyển đổi nhị phân thành
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
973

Khi bạn đã sẵn sàng chuỗi bit của mình, bạn có thể lấy biểu diễn thập phân của nó bằng cách tận dụng ký tự nhị phân

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
15

Đây là một cách nhanh chóng để thực hiện chuyển đổi trong khi làm việc bên trong trình thông dịch Python tương tác. Thật không may, nó sẽ không cho phép bạn chuyển đổi các chuỗi bit được tổng hợp trong thời gian chạy vì tất cả các chữ cần được mã hóa cứng trong mã nguồn

Ghi chú. Bạn có thể muốn đánh giá mã Python bằng

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
993, nhưng đó là một cách dễ dàng để xâm phạm tính bảo mật của chương trình của bạn, vì vậy đừng làm điều đó

Gọi

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994 với hai đối số sẽ hoạt động tốt hơn trong trường hợp chuỗi bit được tạo động

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
16

Đối số đầu tiên là một chuỗi các chữ số, trong khi đối số thứ hai xác định cơ sở của hệ thống số. Không giống như một chữ nhị phân, một chuỗi có thể đến từ bất cứ đâu, ngay cả khi người dùng gõ trên bàn phím. Để có cái nhìn sâu hơn về

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994, bạn có thể mở rộng hộp bên dưới

Các mục đích sử dụng khác của

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994Hiển thị/Ẩn

Có nhiều cách khác để gọi

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994. Ví dụ, nó trả về 0 khi được gọi mà không có đối số

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
17

Tính năng này làm cho nó trở thành một mẫu phổ biến trong bộ sưu tập

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
998, cần một nhà cung cấp giá trị mặc định. Lấy điều này làm ví dụ

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
18

Đây,

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994 giúp đếm số từ trong một câu. Nó được gọi tự động bất cứ khi nào
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
998 cần khởi tạo giá trị của khóa bị thiếu trong từ điển

Một cách sử dụng phổ biến khác của

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994 là đánh máy. Ví dụ: khi bạn chuyển
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994 một giá trị dấu phẩy động, nó sẽ cắt bớt giá trị bằng cách loại bỏ thành phần phân số

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
19

Khi bạn đưa cho nó một chuỗi, nó sẽ cố phân tích một số từ chuỗi đó

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
20

Nói chung,

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994 sẽ chấp nhận một đối tượng thuộc bất kỳ loại nào miễn là nó xác định một phương thức đặc biệt có thể xử lý việc chuyển đổi

Càng xa càng tốt. Nhưng còn số âm thì sao?

Mô phỏng bit dấu hiệu

Khi bạn gọi

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
986 trên một số nguyên âm, nó chỉ thêm dấu trừ vào chuỗi bit thu được từ giá trị dương tương ứng

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
21

Thay đổi dấu của một số không ảnh hưởng đến chuỗi bit cơ bản trong Python. Ngược lại, bạn được phép đặt trước một chuỗi bit bằng dấu trừ khi chuyển đổi nó sang dạng thập phân

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
22

Điều đó có ý nghĩa trong Python bởi vì, bên trong, nó không sử dụng bit dấu. Bạn có thể nghĩ về dấu của một số nguyên trong Python như một phần thông tin được lưu trữ tách biệt với mô đun

Tuy nhiên, có một vài cách giải quyết cho phép bạn mô phỏng các chuỗi bit có độ dài cố định chứa bit dấu

  • Bitmask
  • Hoạt động modulo [
    Line 1 - Value of c is 12
    Line 2 - Value of c is 61
    Line 3 - Value of c is 49
    Line 4 - Value of c is -61
    Line 5 - Value of c is 240
    Line 6 - Value of c is 15
    
    939]
  • Mô-đun
    Line 1 - Value of c is 12
    Line 2 - Value of c is 61
    Line 3 - Value of c is 49
    Line 4 - Value of c is -61
    Line 5 - Value of c is 240
    Line 6 - Value of c is 15
    
    958
  • Mô-đun
    >>> int['00100001', 2]
    33
    
    >>> int['0xff',16]
    255
    
    >>> int['ff', 16]
    255
    
    307
  • mô-đun
    >>> int['00100001', 2]
    33
    
    >>> int['0xff',16]
    255
    
    >>> int['ff', 16]
    255
    
    308

Bạn đã biết từ các phần trước rằng để đảm bảo độ dài bit nhất định của một số, bạn có thể sử dụng mặt nạ bit tiện lợi. Ví dụ: để giữ một byte, bạn có thể sử dụng mặt nạ bao gồm chính xác tám bit được bật

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
23

Mặt nạ buộc Python tạm thời thay đổi biểu diễn của số từ độ lớn của dấu thành phần bù của hai và sau đó quay lại lần nữa. Nếu bạn quên giá trị thập phân của chữ nhị phân kết quả, bằng 21410, thì nó sẽ biểu thị -4210 trong phần bù hai. Bit ngoài cùng bên trái sẽ là bit dấu

Ngoài ra, bạn có thể tận dụng phép toán modulo mà bạn đã sử dụng trước đây để mô phỏng phép dịch phải logic trong Python

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
24

Nếu điều đó có vẻ quá phức tạp đối với sở thích của bạn, thì bạn có thể sử dụng một trong các mô-đun từ thư viện tiêu chuẩn thể hiện cùng một mục đích rõ ràng hơn. Ví dụ: sử dụng

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
958 sẽ có tác dụng giống hệt nhau

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
25

Bạn đã từng thấy nó trước đây, nhưng xin nhắc lại, nó sẽ loại bỏ các kiểu số nguyên không dấu từ C

Một mô-đun tiêu chuẩn khác mà bạn có thể sử dụng cho loại chuyển đổi này trong Python là mô-đun

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
307. Nó xác định cấu trúc dữ liệu tương tự như
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
311 nhưng chỉ được phép chứa các phần tử có cùng kiểu số. Khi khai báo một mảng, bạn cần chỉ định kiểu của nó ở phía trước bằng một chữ cái tương ứng

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
26

Ví dụ:

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
312 là viết tắt của byte có dấu 8 bit, trong khi
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
313 là viết tắt của giá trị tương đương không dấu của nó. Có một số loại được xác định trước khác, chẳng hạn như số nguyên 16 bit có dấu hoặc số dấu phẩy động 32 bit

Sao chép các byte thô giữa hai mảng này sẽ thay đổi cách diễn giải các bit. Tuy nhiên lại chiếm dung lượng bộ nhớ gấp đôi, khá lãng phí. Để thực hiện viết lại bit như vậy tại chỗ, bạn có thể dựa vào mô-đun

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
308, mô-đun này sử dụng một tập hợp tương tự các khai báo kiểu

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
27

Đóng gói cho phép bạn sắp xếp các đối tượng trong bộ nhớ theo các chỉ định kiểu dữ liệu C đã cho. Nó trả về một đối tượng chỉ đọc, chứa các byte thô của khối bộ nhớ kết quả. Sau đó, bạn có thể đọc lại các byte đó bằng cách sử dụng một bộ mã loại khác để thay đổi cách chúng được dịch sang các đối tượng Python

Cho đến thời điểm này, bạn đã sử dụng các kỹ thuật khác nhau để thu được các chuỗi số nguyên có độ dài cố định được biểu thị bằng biểu diễn phần bù của hai. Thay vào đó, nếu bạn muốn chuyển đổi các loại chuỗi bit này thành số nguyên Python, thì bạn có thể thử chức năng này

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
28

Hàm chấp nhận một chuỗi bao gồm các chữ số nhị phân. Đầu tiên, nó chuyển đổi các chữ số thành một số nguyên không dấu đơn giản, bỏ qua bit dấu. Tiếp theo, nó sử dụng hai mặt nạ bit để trích xuất các bit dấu và độ lớn, có vị trí phụ thuộc vào độ dài bit được chỉ định. Cuối cùng, nó kết hợp chúng bằng cách sử dụng số học thông thường, biết rằng giá trị được liên kết với bit dấu là âm

Bạn có thể dùng thử với chuỗi bit cũ đáng tin cậy từ các ví dụ trước đó

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
29

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
994 của Python coi tất cả các bit là độ lớn, vì vậy không có gì ngạc nhiên ở đó. Tuy nhiên, chức năng mới này giả định một chuỗi dài 32 bit theo mặc định, có nghĩa là bit dấu hoàn toàn bằng 0 đối với các chuỗi ngắn hơn. Khi bạn yêu cầu độ dài bit khớp với chuỗi bit của mình, thì bạn sẽ nhận được kết quả như mong đợi

Mặc dù số nguyên là kiểu dữ liệu thích hợp nhất để làm việc với toán tử bitwise trong hầu hết các trường hợp, đôi khi bạn sẽ cần trích xuất và thao tác với các đoạn dữ liệu nhị phân có cấu trúc, chẳng hạn như pixel hình ảnh. Mô-đun

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
307 và
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
308 đề cập ngắn gọn về chủ đề này, vì vậy bạn sẽ khám phá chủ đề này chi tiết hơn trong phần tiếp theo

Xem dữ liệu ở dạng nhị phân

Bạn biết cách đọc và giải thích các byte riêng lẻ. Tuy nhiên, dữ liệu trong thế giới thực thường bao gồm nhiều hơn một byte để truyền tải thông tin. Lấy kiểu dữ liệu

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
968 làm ví dụ. Một số dấu phẩy động duy nhất trong Python chiếm tới tám byte trong bộ nhớ

Làm thế nào để bạn nhìn thấy những byte đó?

Bạn không thể đơn giản sử dụng toán tử bitwise vì chúng không hoạt động với số dấu phẩy động

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
30

Bạn phải quên đi kiểu dữ liệu cụ thể mà bạn đang xử lý và nghĩ về nó dưới dạng một luồng byte chung. Bằng cách đó, sẽ không có vấn đề gì khi các byte đại diện cho bên ngoài ngữ cảnh chúng được xử lý bởi các toán tử bitwise

Để có được

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
315 của một số dấu phẩy động trong Python, bạn có thể đóng gói nó bằng mô-đun
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
308 quen thuộc

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
31

Bỏ qua các ký tự định dạng được chuyển qua đối số đầu tiên. Chúng sẽ không có ý nghĩa gì cho đến khi bạn đến phần bên dưới. Đằng sau cách trình bày văn bản khá tối nghĩa này ẩn chứa một danh sách tám số nguyên

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
32

Các giá trị của chúng tương ứng với các byte tiếp theo được sử dụng để biểu thị số dấu phẩy động ở dạng nhị phân. Bạn có thể kết hợp chúng để tạo ra một chuỗi bit rất dài

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
33

64 bit này là dấu, số mũ và phần định trị với độ chính xác gấp đôi mà bạn đã đọc trước đó. Để tổng hợp một

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
968 từ một chuỗi bit tương tự, bạn có thể đảo ngược quy trình

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
34

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
323 trả về một bộ vì nó cho phép bạn đọc nhiều hơn một giá trị cùng một lúc. Ví dụ: bạn có thể đọc cùng một chuỗi bit dưới dạng bốn số nguyên có dấu 16 bit

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
35

Như bạn có thể thấy, cách diễn giải một chuỗi bit phải được biết trước để tránh kết thúc với dữ liệu bị cắt xén. Một câu hỏi quan trọng bạn cần tự hỏi mình là bạn nên bắt đầu đọc từ đầu nào của luồng byte—trái hay phải. Đọc để tìm hiểu

Thứ tự byte

Không có gì phải bàn cãi về thứ tự các bit trong một byte đơn. Bạn sẽ luôn tìm thấy bit ít quan trọng nhất ở chỉ số 0 và bit quan trọng nhất ở chỉ số bảy, bất kể chúng được sắp xếp vật lý như thế nào trong bộ nhớ. Toán tử dịch chuyển bit dựa vào tính nhất quán này

Tuy nhiên, không có sự đồng thuận về thứ tự byte trong khối dữ liệu nhiều byte. Một đoạn thông tin bao gồm nhiều hơn một byte có thể được đọc từ trái sang phải như văn bản tiếng Anh hoặc từ phải sang trái như văn bản tiếng Ả Rập chẳng hạn. Máy tính nhìn thấy các byte trong một luồng nhị phân giống như con người nhìn thấy các từ trong một câu

Việc máy tính chọn đọc byte từ hướng nào không quan trọng miễn là chúng áp dụng các quy tắc giống nhau ở mọi nơi. Thật không may, các kiến ​​trúc máy tính khác nhau sử dụng các cách tiếp cận khác nhau, khiến việc truyền dữ liệu giữa chúng trở nên khó khăn

Big-Endian vs Little-Endian

Hãy lấy một số nguyên không dấu 32 bit tương ứng với số 196910, là năm mà Monty Python xuất hiện lần đầu trên TV. Với tất cả các số không đứng đầu, nó có biểu diễn nhị phân sau 000000000000000000000111101100012

Làm thế nào bạn sẽ lưu trữ một giá trị như vậy trong bộ nhớ máy tính?

Nếu bạn tưởng tượng bộ nhớ là một cuộn băng một chiều bao gồm các byte, thì bạn cần chia dữ liệu đó thành từng byte riêng lẻ và sắp xếp chúng thành một khối liền kề. Một số thấy bắt đầu từ đầu bên trái là điều tự nhiên vì đó là cách họ đọc, trong khi những người khác thích bắt đầu từ đầu bên phải

Byte Order Address NAddress N+1Address N+2Address N+3 Big-Endian000000002000000002000001112101100012 Little-Endian101100012000001112000000002000000002

Khi các byte được đặt từ trái sang phải, byte quan trọng nhất được gán cho địa chỉ bộ nhớ thấp nhất. Đây được gọi là thứ tự big-endian. Ngược lại, khi các byte được lưu trữ từ phải sang trái, byte ít quan trọng nhất sẽ xuất hiện trước. Đó được gọi là trật tự little-endian

Ghi chú. Những cái tên hài hước này lấy cảm hứng từ cuốn tiểu thuyết thế kỷ 18 Gulliver's Travels của Jonathan Swift. Tác giả mô tả một cuộc xung đột giữa Little-Endians và Big-Endians về cách chính xác để phá vỡ vỏ trứng luộc. Trong khi Little-Endians thích bắt đầu với phần cuối nhỏ nhọn, thì Big-Endians thích phần cuối lớn hơn

Cách nào tốt hơn?

Từ quan điểm thực tế, không có lợi thế thực sự nào khi sử dụng cái này hơn cái kia. Có thể có một số lợi ích nhỏ về hiệu suất ở cấp độ phần cứng, nhưng bạn sẽ không nhận thấy chúng. Các giao thức mạng chính sử dụng thứ tự big-endian, cho phép chúng lọc các gói dữ liệu nhanh hơn dựa trên thiết kế phân cấp địa chỉ IP. Ngoài ra, một số người có thể thấy thuận tiện hơn khi làm việc với một thứ tự byte cụ thể khi gỡ lỗi

Dù bằng cách nào, nếu bạn không hiểu đúng và trộn lẫn hai tiêu chuẩn, thì điều tồi tệ bắt đầu xảy ra

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
36

Khi bạn tuần tự hóa một số giá trị thành một luồng byte bằng một quy ước và thử đọc lại giá trị đó bằng một quy ước khác, bạn sẽ nhận được một kết quả hoàn toàn vô dụng. Trường hợp này rất có thể xảy ra khi dữ liệu được gửi qua mạng, nhưng bạn cũng có thể gặp trường hợp này khi đọc tệp cục bộ ở định dạng cụ thể. Ví dụ: tiêu đề của bitmap Windows luôn sử dụng little-endian, trong khi JPEG có thể sử dụng cả hai thứ tự byte

Bản địa Endianness

Để tìm hiểu độ bền của nền tảng của bạn, bạn có thể sử dụng mô-đun

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
324

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
37

Tuy nhiên, bạn không thể thay đổi tuổi thọ vì đó là một tính năng nội tại của kiến ​​trúc CPU của bạn. Không thể chế nhạo nó cho mục đích thử nghiệm mà không có ảo hóa phần cứng như QEMU, vì vậy ngay cả VirtualBox phổ biến cũng không giúp được gì

Đáng chú ý, dòng vi xử lý x86 của Intel và AMD, cung cấp năng lượng cho hầu hết các máy tính xách tay và máy tính để bàn hiện đại, đều là những bộ vi xử lý nhỏ. Các thiết bị di động dựa trên kiến ​​trúc ARM năng lượng thấp, trong khi một số kiến ​​trúc cũ hơn như Motorola 68000 cổ đại chỉ dành cho thiết bị lớn.

Để biết thông tin về cách xác định tuổi thọ trong C, hãy mở rộng hộp bên dưới

Kiểm tra thứ tự byte trong CHiển thị/Ẩn

Trước đây, cách để có được độ bền của máy trong C là khai báo một số nguyên nhỏ và sau đó đọc byte đầu tiên của nó bằng một con trỏ

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
38

Nếu giá trị xuất hiện cao hơn 0, thì byte được lưu trữ ở địa chỉ bộ nhớ thấp nhất phải là byte có ý nghĩa nhỏ nhất

Khi bạn biết độ bền gốc của máy, bạn sẽ muốn chuyển đổi giữa các thứ tự byte khác nhau khi thao tác dữ liệu nhị phân. Một cách phổ biến để làm như vậy, bất kể loại dữ liệu hiện có, là đảo ngược một đối tượng chung chung

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
315 hoặc một chuỗi các số nguyên đại diện cho các byte đó

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
39

Tuy nhiên, thường thuận tiện hơn khi sử dụng mô-đun

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
308, mô-đun này cho phép bạn xác định các kiểu dữ liệu C tiêu chuẩn. Ngoài ra, nó cho phép bạn yêu cầu một thứ tự byte nhất định với một công cụ sửa đổi tùy chọn

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
60

Dấu lớn hơn [

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
327] chỉ ra rằng các byte được sắp xếp theo thứ tự lớn về cuối, trong khi ký hiệu nhỏ hơn [
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
328] tương ứng với nhỏ về cuối. Nếu bạn không chỉ định một, thì tuổi thọ gốc được giả định. Có một số công cụ sửa đổi khác, chẳng hạn như dấu chấm than [
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
329], biểu thị thứ tự byte mạng

Thứ tự byte mạng

Mạng máy tính được tạo thành từ các thiết bị không đồng nhất như máy tính xách tay, máy tính để bàn, máy tính bảng, điện thoại thông minh và thậm chí cả bóng đèn được trang bị bộ điều hợp Wi-Fi. Tất cả chúng đều cần các giao thức và tiêu chuẩn đã được thống nhất, bao gồm cả thứ tự byte để truyền nhị phân, để giao tiếp hiệu quả

Vào buổi bình minh của Internet, người ta đã quyết định rằng thứ tự byte cho các giao thức mạng đó sẽ là big-endian

Các chương trình muốn giao tiếp qua mạng có thể lấy API C cổ điển, loại bỏ các chi tiết khó hiểu bằng một lớp ổ cắm. Python kết thúc API đó thông qua mô-đun

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
330 tích hợp. Tuy nhiên, trừ khi bạn đang viết một giao thức nhị phân tùy chỉnh, có thể bạn sẽ muốn tận dụng lợi thế của sự trừu tượng hóa ở mức cao hơn, chẳng hạn như giao thức HTTP, dựa trên văn bản

Trường hợp mô-đun

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
330 có thể hữu ích là chuyển đổi thứ tự byte. Nó hiển thị một số chức năng từ API C, với các tên xoắn lưỡi, đặc biệt của chúng

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
61

Nếu máy chủ của bạn đã sử dụng thứ tự byte cuối lớn, thì không cần phải làm gì nữa. Các giá trị sẽ được giữ nguyên

Bitmasks

Một bitmask hoạt động giống như một khuôn tô graffiti ngăn không cho sơn phun lên các khu vực cụ thể của bề mặt. Nó cho phép bạn cô lập các bit để áp dụng một số chức năng trên chúng một cách có chọn lọc. Bitmasking liên quan đến cả toán tử logic theo bit và toán tử dịch chuyển theo bit mà bạn đã đọc về

Bạn có thể tìm thấy bitmask trong nhiều ngữ cảnh khác nhau. Ví dụ: mặt nạ mạng con trong địa chỉ IP thực chất là một bitmask giúp bạn trích xuất địa chỉ mạng. Các kênh pixel, tương ứng với các màu đỏ, lục và lam trong mô hình RGB, có thể được truy cập bằng bitmask. Bạn cũng có thể sử dụng một bitmask để xác định các cờ Boolean mà sau đó bạn có thể đóng gói trên một trường bit

Có một số loại hoạt động phổ biến liên quan đến bitmasks. Bạn sẽ có một cái nhìn nhanh về một số trong số họ dưới đây

nhận được một chút

Để đọc giá trị của một bit cụ thể trên một vị trí nhất định, bạn có thể sử dụng bit AND đối với mặt nạ bit chỉ bao gồm một bit tại chỉ mục mong muốn

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
62

Mặt nạ sẽ chặn tất cả các bit ngoại trừ bit mà bạn quan tâm. Nó sẽ dẫn đến kết quả bằng 0 hoặc lũy thừa hai với số mũ bằng chỉ số bit. Thay vào đó, nếu bạn muốn nhận được câu trả lời có hoặc không đơn giản, thì bạn có thể chuyển sang bên phải và kiểm tra bit ít quan trọng nhất

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
63

Lần này, nó sẽ chuẩn hóa giá trị bit để nó không bao giờ vượt quá một. Sau đó, bạn có thể sử dụng hàm đó để lấy giá trị Boolean ________ 1928 hoặc ________ 1929 thay vì giá trị số

Đặt một Bit

Đặt một chút cũng tương tự như lấy một. Bạn tận dụng cùng một bitmask như trước, nhưng thay vì sử dụng AND theo bit, bạn sử dụng toán tử OR theo bit

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
64

Mặt nạ giữ lại tất cả các bit ban đầu trong khi thực thi một bit nhị phân tại chỉ mục đã chỉ định. Nếu bit đó đã được đặt, giá trị của nó sẽ không thay đổi

Gỡ cài đặt một Bit

Để xóa một chút, bạn muốn sao chép tất cả các chữ số nhị phân trong khi thực thi số 0 tại một chỉ mục cụ thể. Bạn có thể đạt được hiệu ứng này bằng cách sử dụng lại cùng một bitmask, nhưng ở dạng đảo ngược

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
65

Sử dụng bitwise NOT trên một số dương luôn tạo ra một giá trị âm trong Python. Mặc dù điều này nói chung là không mong muốn, nhưng nó không thành vấn đề ở đây vì bạn ngay lập tức áp dụng toán tử AND theo chiều bit. Đến lượt nó, điều này kích hoạt chuyển đổi của mặt nạ thành biểu diễn bổ sung của hai, mang lại cho bạn kết quả như mong đợi

Chuyển đổi một chút

Đôi khi, thật hữu ích khi có thể bật và tắt một chút định kỳ. Đó là một cơ hội hoàn hảo cho toán tử XOR bitwise, có thể lật ngược bit của bạn như thế

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
66

Lưu ý cùng một bitmask được sử dụng lại. Một nhị phân trên vị trí đã chỉ định sẽ làm cho bit tại chỉ mục đó đảo ngược giá trị của nó. Việc có các số 0 nhị phân ở những vị trí còn lại sẽ đảm bảo rằng phần còn lại của các bit sẽ được sao chép

Quá tải toán tử Bitwise

Miền chính của toán tử bitwise là số nguyên. Đó là nơi chúng có ý nghĩa nhất. Tuy nhiên, bạn cũng đã thấy chúng được sử dụng trong ngữ cảnh Boolean, trong đó chúng thay thế các toán tử logic. Python cung cấp các triển khai thay thế cho một số toán tử của nó và cho phép bạn nạp chồng chúng cho các kiểu dữ liệu mới

Mặc dù đề xuất quá tải các toán tử logic trong Python đã bị từ chối, nhưng bạn có thể đưa ra ý nghĩa mới cho bất kỳ toán tử theo bit nào. Nhiều thư viện phổ biến và thậm chí cả thư viện tiêu chuẩn, tận dụng lợi thế của nó

Các kiểu dữ liệu tích hợp

Các toán tử bitwise trong Python được xác định cho các kiểu dữ liệu tích hợp sau

  • Line 1 - Value of c is 12
    Line 2 - Value of c is 61
    Line 3 - Value of c is 49
    Line 4 - Value of c is -61
    Line 5 - Value of c is 240
    Line 6 - Value of c is 15
    
    973
  • >>> int['00100001', 2]
    33
    
    >>> int['0xff',16]
    255
    
    >>> int['ff', 16]
    255
    
    335
  • >>> int['00100001', 2]
    33
    
    >>> int['0xff',16]
    255
    
    >>> int['ff', 16]
    255
    
    336 và
  • >>> int['00100001', 2]
    33
    
    >>> int['0xff',16]
    255
    
    >>> int['ff', 16]
    255
    
    338 [kể từ Python 3. 9]

Đó không phải là một thực tế được biết đến rộng rãi, nhưng các toán tử bitwise có thể thực hiện các phép toán từ đại số tập hợp, chẳng hạn như hợp, giao và hiệu đối xứng, cũng như hợp nhất và cập nhật từ điển

Ghi chú. Tại thời điểm viết bài, Python 3. 9 chưa được phát hành, nhưng bạn có thể xem trước các tính năng ngôn ngữ sắp tới bằng cách sử dụng Docker hoặc pyenv

Khi

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
931 và
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
932 là các bộ Python, thì các toán tử bitwise tương ứng với các phương thức sau

Set MethodBitwise Operator

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
341
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
4____4343
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
909
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
345
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
2
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
347
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
906
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
349
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
6
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
351
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
912

Chúng hầu như làm cùng một việc, vì vậy việc sử dụng cú pháp nào là tùy thuộc vào bạn. Ngoài ra, còn có một toán tử trừ đã quá tải [

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
964], thực hiện hiệu của hai tập hợp. Để xem chúng hoạt động như thế nào, giả sử bạn có hai nhóm trái cây và rau củ sau đây

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
67

Họ chia sẻ một thành viên chung, rất khó để phân loại, nhưng phần còn lại của các yếu tố của họ là rời rạc

Một điều cần chú ý là

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
354 bất biến, thiếu các phương thức cập nhật tại chỗ. Tuy nhiên, khi bạn sử dụng các đối tác toán tử bitwise của chúng, ý nghĩa hơi khác một chút

>>>

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
68

Rốt cuộc, có vẻ như

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
354 không phải là bất biến khi bạn sử dụng các toán tử bitwise, nhưng vấn đề nằm ở chi tiết. Đây là những gì thực sự xảy ra

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
69

Lý do nó hoạt động lần thứ hai là bạn không thay đổi đối tượng bất biến ban đầu. Thay vào đó, bạn tạo một cái mới và gán lại nó cho cùng một biến

Python

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
338 chỉ hỗ trợ bit OR, hoạt động giống như toán tử hợp. Bạn có thể sử dụng nó để cập nhật một từ điển tại chỗ hoặc hợp nhất hai từ điển thành một từ điển mới

>>>

>>> [age >= 18] & ~is_self_excluded
0
0

Phiên bản tăng cường của toán tử bitwise tương đương với

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
357

Mô-đun của bên thứ ba

Nhiều thư viện phổ biến, bao gồm NumPy, pandas và SQLAlchemy, làm quá tải các toán tử bitwise cho các kiểu dữ liệu cụ thể của chúng. Đây là nơi rất có thể bạn sẽ tìm thấy các toán tử bitwise trong Python vì chúng không còn được sử dụng thường xuyên theo nghĩa gốc của chúng nữa

Ví dụ: NumPy áp dụng chúng cho dữ liệu được vector hóa theo kiểu điểm

>>>

>>> [age >= 18] & ~is_self_excluded
0
1

Bằng cách này, bạn không cần phải áp dụng thủ công cùng một toán tử từng bit cho từng phần tử của mảng. Nhưng bạn không thể làm điều tương tự với danh sách thông thường trong Python

gấu trúc sử dụng NumPy đằng sau hậu trường và nó cũng cung cấp các phiên bản quá tải của toán tử bitwise cho các đối tượng

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
358 và
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
359 của nó. Tuy nhiên, họ cư xử như bạn mong đợi. Sự khác biệt duy nhất là chúng thực hiện công việc thông thường của chúng trên các vectơ và ma trận của các số thay vì trên các đại lượng vô hướng riêng lẻ

Mọi thứ trở nên thú vị hơn với các thư viện cung cấp cho các toán tử bitwise những ý nghĩa hoàn toàn mới. Ví dụ, SQLAlchemy cung cấp một cú pháp nhỏ gọn để truy vấn cơ sở dữ liệu

>>> [age >= 18] & ~is_self_excluded
0
2

Toán tử AND theo bit [

>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
1] cuối cùng sẽ dịch thành một đoạn truy vấn SQL. Tuy nhiên, điều đó không rõ ràng lắm, ít nhất là không phải với IDE của tôi, nó phàn nàn về việc sử dụng các toán tử bitwise không phức tạp khi nó nhìn thấy chúng trong loại biểu thức này. Nó ngay lập tức gợi ý thay thế mọi lần xuất hiện của
>>> def call[x]:
..     print[f"call[{x=}]"]
..     return x
...
>>> call[False] or call[True]  # Both operands evaluated
call[x=False]
call[x=True]
True
>>> call[True] or call[False]  # Only the left operand evaluated
call[x=True]
True
1 bằng một
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
925 hợp lý, mà không biết rằng làm như vậy sẽ khiến mã ngừng hoạt động

Kiểu nạp chồng toán tử này là một phương pháp gây tranh cãi dựa trên phép thuật tiềm ẩn mà bạn phải biết trước. Một số ngôn ngữ lập trình như Java ngăn chặn sự lạm dụng đó bằng cách không cho phép quá tải toán tử hoàn toàn. Python tự do hơn về vấn đề đó và tin tưởng rằng bạn biết mình đang làm gì

Loại dữ liệu tùy chỉnh

Để tùy chỉnh hành vi của các toán tử bitwise của Python, bạn phải định nghĩa một lớp và sau đó triển khai lớp tương ứng trong đó. Đồng thời, bạn không thể xác định lại hành vi của toán tử bitwise cho các loại hiện có. Quá tải toán tử chỉ có thể thực hiện được trên các kiểu dữ liệu mới

Dưới đây là tóm tắt nhanh về các phương thức đặc biệt cho phép bạn quá tải các toán tử theo bit

Magic MethodExpression

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
363
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
364
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
365
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
366
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
367
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
368
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
369
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
370
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
371
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
372
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
373
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
374
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
375
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
376
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
377
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
378
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
379
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
380
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
381
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
382
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
383
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
384
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
385
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
386
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
387
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
388
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
389
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
390
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
391
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
392
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
393
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
394

Bạn không cần phải xác định tất cả chúng. Ví dụ: để có một cú pháp thuận tiện hơn một chút để nối thêm và thêm các phần tử vào a , chỉ cần triển khai

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
395 và
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
396 là đủ

>>>

>>> [age >= 18] & ~is_self_excluded
0
3

Lớp do người dùng định nghĩa này bao bọc một deque để tái sử dụng triển khai của nó và bổ sung thêm cho nó hai phương thức bổ sung cho phép thêm các mục vào đầu bên trái hoặc bên phải của bộ sưu tập

Steganography bit ít quan trọng nhất

Whew, đó là rất nhiều để xử lý. Nếu bạn vẫn đang vò đầu bứt tai, tự hỏi tại sao bạn lại muốn sử dụng toán tử bitwise, thì đừng lo lắng. Đã đến lúc thể hiện những gì bạn có thể làm với chúng một cách thú vị

Để làm theo các ví dụ trong phần này, bạn có thể tải xuống mã nguồn bằng cách nhấp vào liên kết bên dưới

Lấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về các toán tử bitwise của Python trong hướng dẫn này

Bạn sẽ tìm hiểu về steganography và áp dụng khái niệm này để nhúng bí mật các tập tin tùy ý vào các hình ảnh bitmap

Mật mã vs Steganography

Mật mã là về việc thay đổi một tin nhắn thành một tin nhắn chỉ có thể đọc được đối với những người có khóa phù hợp. Mọi người khác vẫn có thể xem tin nhắn được mã hóa, nhưng nó sẽ không có ý nghĩa gì với họ. Một trong những dạng mật mã đầu tiên là mật mã thay thế, chẳng hạn như mật mã được đặt theo tên của Julius Caesar

Steganography tương tự như mật mã vì nó cũng cho phép bạn chia sẻ các tin nhắn bí mật với đối tượng mong muốn của mình. Tuy nhiên, thay vì sử dụng mã hóa, nó khéo léo giấu thông tin trong một phương tiện không thu hút sự chú ý. Các ví dụ bao gồm sử dụng mực vô hình hoặc viết một chữ cái đầu trong đó chữ cái đầu tiên của mỗi từ hoặc dòng tạo thành một thông điệp bí mật

Trừ khi bạn biết rằng một tin nhắn bí mật đã bị che giấu và phương pháp khôi phục nó, nếu không bạn có thể bỏ qua nhà cung cấp dịch vụ. Bạn có thể kết hợp cả hai kỹ thuật để an toàn hơn, ẩn tin nhắn được mã hóa thay vì tin nhắn gốc

Có rất nhiều cách để buôn lậu dữ liệu bí mật trong thế giới kỹ thuật số. Đặc biệt, các định dạng tệp chứa nhiều dữ liệu, chẳng hạn như tệp âm thanh, video hoặc hình ảnh, rất phù hợp vì chúng cho bạn nhiều không gian để làm việc. Ví dụ, các công ty phát hành tài liệu có bản quyền có thể sử dụng kỹ thuật ghi ảnh để đánh dấu các bản sao riêng lẻ và truy tìm nguồn rò rỉ

Bên dưới, bạn sẽ đưa dữ liệu bí mật vào một bitmap đơn giản, dễ đọc và ghi bằng Python mà không cần phụ thuộc bên ngoài

Định dạng tệp bitmap

Từ bitmap thường dùng để chỉ định dạng tệp Windows bitmap [______4397], hỗ trợ một số cách biểu diễn pixel thay thế. Để làm cho cuộc sống dễ dàng hơn, bạn sẽ giả sử rằng các pixel được lưu trữ ở định dạng RGB [đỏ, lục và lam] 24 bit không nén. Một pixel sẽ có ba kênh màu, mỗi kênh có thể chứa các giá trị từ 010 đến 25510

Mỗi bitmap bắt đầu bằng một tiêu đề tệp, chứa siêu dữ liệu như chiều rộng và chiều cao của hình ảnh. Dưới đây là một vài trường thú vị và vị trí của chúng so với phần đầu của tiêu đề

FieldByte OffsetBytes LengthTypeSample ValueSignature

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
3982StringBMFile Size
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
3994Unsigned int7,629,186Reserved #1
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7002Bytes0Reserved #2
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7012Bytes0Pixels Offset
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7024Unsigned int122Pixels Size
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7034Unsigned int7,629,064Image Width
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7044Unsigned int1,954Image Height
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7054Unsigned int1,301Bits Per Pixel
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7062Unsigned short24Compression
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7074Unsigned int0Colors Palette
>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
7084Unsigned int0

Bạn có thể suy ra từ tiêu đề này rằng bitmap tương ứng rộng 1.954 pixel và cao 1.301 pixel. Nó không sử dụng nén, cũng không có bảng màu. Mỗi pixel chiếm 24 bit hoặc 3 byte và dữ liệu pixel thô bắt đầu ở offset 12210

Bạn có thể mở bitmap ở chế độ nhị phân, tìm kiếm phần bù mong muốn, đọc số byte đã cho và giải tuần tự hóa chúng bằng cách sử dụng

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
308 như trước đây

>>> [age >= 18] & ~is_self_excluded
0
4

Lưu ý rằng tất cả các trường số nguyên trong ảnh bitmap được lưu trữ theo thứ tự byte cuối nhỏ

Bạn có thể đã nhận thấy sự khác biệt nhỏ giữa số byte pixel được khai báo trong tiêu đề và số byte do kích thước hình ảnh. Khi bạn nhân 1.954 pixel × 1.301 pixel × 3 byte, bạn sẽ nhận được giá trị nhỏ hơn 2.602 byte so với 7.629.064

Điều này là do byte pixel được đệm bằng số 0 để mỗi hàng là bội số của bốn byte. Nếu chiều rộng của hình ảnh nhân với ba byte là bội số của bốn thì không cần đệm. Mặt khác, các byte trống được thêm vào cuối mỗi hàng

Ghi chú. Để tránh gây nghi ngờ, bạn cần tính đến phần đệm đó bằng cách bỏ qua các byte trống. Nếu không, nó sẽ là một món quà rõ ràng cho người biết phải tìm gì

Bitmap lưu trữ các hàng pixel lộn ngược, bắt đầu từ dưới cùng thay vì trên cùng. Ngoài ra, mọi pixel được tuần tự hóa thành một vectơ kênh màu theo thứ tự BGR hơi kỳ quặc thay vì RGB. Tuy nhiên, điều này không liên quan đến nhiệm vụ che giấu dữ liệu bí mật

Bitwise Ẩn và Tìm kiếm

Bạn có thể sử dụng toán tử bitwise để trải rộng dữ liệu tùy chỉnh trên các byte pixel liên tiếp. Ý tưởng là ghi đè bit ít quan trọng nhất trong mỗi bit bằng các bit đến từ byte bí mật tiếp theo. Điều này sẽ tạo ra ít nhiễu nhất, nhưng bạn có thể thử nghiệm thêm nhiều bit hơn để đạt được sự cân bằng giữa kích thước của dữ liệu được đưa vào và độ méo pixel

Ghi chú. Sử dụng chức năng ghi bit ít quan trọng nhất không ảnh hưởng đến kích thước tệp của ảnh bitmap thu được. Nó sẽ giữ nguyên như tệp gốc

Trong một số trường hợp, các bit tương ứng sẽ giống nhau, dẫn đến không có thay đổi nào về giá trị pixel. Tuy nhiên, ngay cả trong trường hợp xấu nhất, màu pixel sẽ chỉ khác một phần trăm. Một sự bất thường nhỏ như vậy sẽ không thể nhìn thấy bằng mắt người nhưng có thể được phát hiện bằng phân tích ẩn, sử dụng số liệu thống kê

Hãy xem những hình ảnh cắt này

Hình bên trái lấy từ bitmap gốc, trong khi hình ảnh bên phải mô tả một bitmap đã xử lý với video nhúng được lưu trữ trên các bit ít quan trọng nhất. Bạn có thể nhận ra sự khác biệt?

Đoạn mã sau mã hóa dữ liệu bí mật vào bitmap

>>> [age >= 18] & ~is_self_excluded
0
5

Đối với mỗi byte dữ liệu bí mật và tám byte dữ liệu pixel tương ứng, không bao gồm các byte đệm, nó chuẩn bị một danh sách các bit sẽ được trải rộng. Tiếp theo, nó ghi đè lên bit ít quan trọng nhất trong mỗi tám byte bằng cách sử dụng mặt nạ bit có liên quan. Kết quả được chuyển đổi thành một đối tượng

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
315 và được gán trở lại phần bitmap ban đầu của nó

Để giải mã một tệp từ cùng một bitmap, bạn cần biết có bao nhiêu byte bí mật đã được ghi vào đó. Bạn có thể phân bổ một vài byte ở đầu luồng dữ liệu để lưu trữ số này hoặc bạn có thể sử dụng các trường dành riêng từ tiêu đề bitmap

>>> [age >= 18] & ~is_self_excluded
0
6

Thao tác này chuyển sang phần bù bên phải trong tệp, tuần tự hóa Python

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
973 thành byte thô và ghi chúng xuống

Bạn cũng có thể muốn lưu trữ tên của tệp bí mật của mình. Vì nó có thể có độ dài tùy ý, nên tuần tự hóa nó bằng cách sử dụng chuỗi kết thúc null, sẽ đứng trước nội dung tệp. Để tạo một chuỗi như vậy, bạn cần mã hóa một đối tượng Python

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
712 thành byte và nối thêm byte rỗng ở cuối theo cách thủ công

>>>

>>> [age >= 18] & ~is_self_excluded
0
7

Ngoài ra, việc xóa thư mục mẹ dư thừa khỏi đường dẫn bằng cách sử dụng

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
713 cũng không hại gì

Mã mẫu bổ sung cho bài viết này sẽ cho phép bạn mã hóa, giải mã và xóa một tệp bí mật khỏi ảnh bitmap đã cho bằng các lệnh sau

>>> [age >= 18] & ~is_self_excluded
0
8

Đây là một mô-đun có thể chạy được, có thể được thực thi bằng cách gọi thư mục bao gồm của nó. Bạn cũng có thể tạo một kho lưu trữ định dạng ZIP di động từ nội dung của nó để tận dụng hỗ trợ ứng dụng Python ZIP

Chương trình này dựa trên các mô-đun từ thư viện chuẩn được đề cập trong bài viết và một số mô-đun khác mà bạn có thể chưa từng nghe đến trước đây. Một mô-đun quan trọng là

>>> int['00100001', 2]
33

>>> int['0xff',16]
255

>>> int['ff', 16]
255
714, hiển thị giao diện Python cho các tệp ánh xạ bộ nhớ. Chúng cho phép bạn thao tác với các tệp lớn bằng cả API tệp tiêu chuẩn và API trình tự. Như thể tệp là một danh sách lớn có thể thay đổi mà bạn có thể cắt

Hãy tiếp tục và chơi xung quanh với bitmap được đính kèm với các tài liệu hỗ trợ. Nó chứa một chút ngạc nhiên cho bạn

Phần kết luận

Nắm vững các toán tử bitwise Python mang lại cho bạn sự tự do tối đa để thao tác dữ liệu nhị phân trong các dự án của bạn. Bây giờ bạn đã biết cú pháp của chúng và các hương vị khác nhau cũng như các kiểu dữ liệu hỗ trợ chúng. Bạn cũng có thể tùy chỉnh hành vi của họ cho nhu cầu của riêng bạn

Trong hướng dẫn này, bạn đã học cách

  • Sử dụng các toán tử bitwise Python để thao tác các bit riêng lẻ
  • Đọc và ghi dữ liệu nhị phân theo cách bất khả tri trên nền tảng
  • Sử dụng bitmasks để đóng gói thông tin trên một byte đơn
  • Quá tải toán tử bitwise Python trong các loại dữ liệu tùy chỉnh
  • Ẩn tin nhắn bí mật trong hình ảnh kỹ thuật số

Bạn cũng đã học cách máy tính sử dụng hệ thống nhị phân để biểu diễn các loại thông tin kỹ thuật số khác nhau. Bạn đã thấy một số cách phổ biến để diễn giải các bit và cách giảm thiểu việc thiếu các kiểu dữ liệu không dấu trong Python cũng như cách lưu trữ số nguyên duy nhất của Python trong bộ nhớ

Với thông tin này, bạn đã sẵn sàng sử dụng toàn bộ dữ liệu nhị phân trong mã của mình. Để tải xuống mã nguồn được sử dụng trong ví dụ thủy ấn và tiếp tục thử nghiệm với các toán tử bitwise, bạn có thể nhấp vào liên kết bên dưới

Lấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về các toán tử bitwise của Python trong hướng dẫn này

Đánh dấu là đã hoàn thành

Xem ngay Hướng dẫn này có một khóa học video liên quan do nhóm Real Python tạo. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn. Toán tử nhị phân, byte và bit trong Python

🐍 Thủ thuật Python 💌

Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python

Gửi cho tôi thủ thuật Python »

Giới thiệu về Bartosz Zaczyński

Bartosz là người hướng dẫn bootcamp, tác giả và lập trình viên đa ngôn ngữ yêu thích Python. Anh ấy giúp sinh viên của mình tiếp cận công nghệ phần mềm bằng cách chia sẻ kinh nghiệm thương mại hơn một thập kỷ trong ngành CNTT

» Thông tin thêm về Bartosz

Mỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là

Aldren

David

Geir Arne

Joanna

Gia-cốp

Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bậc thầy Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bạn nghĩ sao?

Đánh giá bài viết này

Tweet Chia sẻ Chia sẻ Email

Bài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?

Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi

Bit có nghĩa là gì trong Python?

Máy tính lưu trữ tất cả các loại thông tin dưới dạng luồng chữ số nhị phân được gọi là bit. Cho dù bạn đang làm việc với văn bản, hình ảnh hay video, tất cả chúng đều biến thành số 1 và 0. Các toán tử bitwise của Python cho phép bạn thao tác các bit dữ liệu riêng lẻ đó ở mức chi tiết nhất.

Có bao nhiêu bit trong Python?

Bit và byte . Hầu hết các máy tính hiện đại đều là kiến ​​trúc 64-bit mà Python 3 sẽ sử dụng 64-bit để biểu diễn các số. Một số máy tính có thể là kiến ​​trúc 32 bit và Python có thể sử dụng 32 bit để biểu thị số - hãy cẩn thận.

Chủ Đề