Apa biner di python?

Saya mengeksplorasi cara membuat lingkungan virtual di Sublime Text3 dan menemukan paket bernama Virtualenv. Saya memiliki pertanyaan tentang membuat lingkungan virtual baru. Ini dokumentasinya

Membuat virtualenv

Pilih Virtualenv: New (atau Virtualenv: New (venv) untuk virtualenv bawaan), ketik jalur tujuan dan pilih biner python. Virtualenv baru akan diaktifkan secara otomatis

My question is, what is a python binary and what is its importance (I cant seem to find the term anywhere online). Here is what pops out after I specify the folder name and thus the destination path

Computers store all kinds of information as a stream of binary digits called bits. Whether you’re working with text, images, or videos, they all boil down to ones and zeros. Python’s bitwise operators let you manipulate those individual bits of data at the most granular level

You can use bitwise operators to implement algorithms such as compression, encryption, and error detection as well as to control physical devices in your Raspberry Pi project or elsewhere. Often, Python isolates you from the underlying bits with high-level abstractions. You’re more likely to find the overloaded flavors of bitwise operators in practice. But when you work with them in their original form, you’ll be surprised by their quirks

In this tutorial, you’ll learn how to

  • Use Python bitwise operators to manipulate individual bits
  • Read and write binary data in a platform-agnostic way
  • Use bitmasks to pack information on a single byte
  • Overload Python bitwise operators in custom data types
  • Hide secret messages in digital images

To get the complete source code of the digital watermarking example, and to extract a secret treat hidden in an image, click the link below

Get the Source Code. Click here to get the source code you’ll use to learn about Python’s bitwise operators in this tutorial

Overview of Python’s Bitwise Operators

Python comes with a few different kinds of operators, such as the arithmetic, logical, and comparison operators. You can think of them as functions that take advantage of a more compact prefix and infix syntax

Note. Python does not include postfix operators like the increment (

>>> (age >= 18) & ~is_self_excluded
0
9) or decrement (
>>> 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) operators available in C

Bitwise operators look virtually the same across different programming languages

OperatorExampleMeaning

>>> 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
>>> 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 (exclusive 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
>>> (42).bit_length()
6
00Bitwise left shift
>>> (42).bit_length()
6
01
>>> (42).bit_length()
6
02Bitwise right shift

As you can see, they’re denoted with strange-looking symbols instead of words. This makes them stand out in Python as slightly less verbose than you might be used to seeing. Anda mungkin tidak akan bisa mengetahui artinya hanya dengan melihatnya

Note. If you’re coming from another programming language such as Java, then you’ll immediately notice that Python is missing the unsigned right shift operator denoted by three greater-than signs (

>>> (42).bit_length()
6
03)

This has to do with how Python internally. Karena bilangan bulat dalam Python dapat memiliki jumlah bit yang tak terbatas, bit tanda tidak memiliki posisi tetap. Faktanya, tidak ada tanda sama sekali di Python

Sebagian besar operator bitwise adalah biner, yang berarti mereka mengharapkan dua operan untuk bekerja dengannya, biasanya disebut sebagai operan kiri dan operan kanan. 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) adalah satu-satunya operator bitwise unary karena hanya mengharapkan satu operan

Semua operator bitwise biner memiliki operator gabungan yang sesuai yang melakukan penugasan tambahan

OperatorExampleEquivalent to

>>> (42).bit_length()
6
05
>>> (42).bit_length()
6
06
>>> (42).bit_length()
6
07
>>> (42).bit_length()
6
08
>>> (42).bit_length()
6
09
>>> (42).bit_length()
6
10
>>> (42).bit_length()
6
11
>>> (42).bit_length()
6
12
>>> (42).bit_length()
6
13
>>> (42).bit_length()
6
14
>>> (42).bit_length()
6
15
>>> (42).bit_length()
6
16
>>> (42).bit_length()
6
17
>>> (42).bit_length()
6
18
>>> (42).bit_length()
6
19

These are shorthand notations for updating the left operand in place

That’s all there is to Python’s bitwise operator syntax. Now you’re ready to take a closer look at each of the operators to understand where they’re most useful and how you can use them. First, you’ll get a quick refresher on the binary system before looking at two categories of bitwise operators. the bitwise logical operators and the bitwise shift operators

Remove ads

Binary System in Five Minutes

Before moving on, take a moment to brush up your knowledge of the binary system, which is essential to understanding bitwise operators. If you’re already comfortable with it, then go ahead and jump to the section below

Mengapa Menggunakan Biner?

There are an infinite number of ways to represent numbers. Since ancient times, people have developed different notations, such as Roman numerals and Egyptian hieroglyphs. Most modern civilizations use positional notation, which is efficient, flexible, and well suited for doing arithmetic

A notable feature of any positional system is its base, which represents the number of digits available. People naturally favor the base-ten numeral system, also known as the decimal system, because it plays nicely with counting on fingers

Computers, on the other hand, treat data as a bunch of numbers expressed in the base-two numeral system, more commonly known as the binary system. Such numbers are composed of only two digits, zero and one

Note. In math books, the base of a numeric literal is commonly denoted with a subscript that appears slightly below the baseline, such as 4210

For example, the binary number 100111002 is equivalent to 15610 in the base-ten system. Because there are ten numerals in the decimal system—zero through nine—it usually takes fewer digits to write the same number in base ten than in base two

Note. You can’t tell a numeral system just by looking at a given number’s digits

For example, the decimal number 10110 happens to use only binary digits. But it represents a completely different value than its binary counterpart, 1012, which is equivalent to 510

The binary system requires more storage space than the decimal system but is much less complicated to implement in hardware. While you need more building blocks, they’re easier to make, and there are fewer types of them. That’s like breaking down your code into more modular and reusable pieces

More importantly, however, the binary system is perfect for electronic devices, which translate digits into different voltage levels. Because voltage likes to drift up and down due to various kinds of noise, you want to keep sufficient distance between consecutive voltages. Otherwise, the signal might end up distorted

By employing only two states, you make the system more reliable and resistant to noise. Alternatively, you could jack up the voltage, but that would also increase the power consumption, which you definitely want to avoid

How Does Binary Work?

Imagine for a moment that you had only two fingers to count on. You could count a zero, a one, and a two. But when you ran out of fingers, you’d need to note how many times you had already counted to two and then start over until you reached two again

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

Every time you wrote down another pair of fingers, you’d also need to group them by powers of two, which is the base of the system. For example, to count up to thirteen, you would have to use both of your fingers six times and then use one more finger. Your fingers could be arranged as one eight, one four, and one one

These powers of two correspond to digit positions in a binary number and tell you exactly which bits to switch on. They grow right to left, starting at the least-significant bit, which determines if the number is even or odd

Positional notation is like the odometer in your car. Once a digit in a particular position reaches its maximum value, which is one in the binary system, it rolls over to zero and the one carries over to the left. This can have a cascading effect if there are already some ones to the left of the digit

How Computers Use Binary

Now that you know the basic principles of the binary system and why computers use it, you’re ready to learn how they represent data with it

Before any piece of information can be reproduced in digital form, you have to break it down into numbers and then convert them to the binary system. For example, plain text can be thought of as a string of characters. You could assign an arbitrary number to each character or pick an existing character encoding such as ASCII, ISO-8859-1, or UTF-8

In Python, strings are represented as arrays of Unicode code points. To reveal their ordinal values, call

>>> (42).bit_length()
6
20 on each of the characters

>>>

>>> [ord(character) for character in "€uro"]
[8364, 117, 114, 111]

The resulting numbers uniquely identify the text characters within the Unicode space, but they’re shown in decimal form. You want to rewrite them using binary digits

CharacterDecimal Code PointBinary Code Point€836410100000101011002u1171011101012r1141011100102o1111011011112

Notice that bit-length, which is the number of binary digits, varies greatly across the characters. The euro sign (

>>> (42).bit_length()
6
21) requires fourteen bits, while the rest of the characters can comfortably fit on seven bits

Note. Here’s how you can check the bit-length of any integer number in Python

>>>

>>> (42).bit_length()
6

Without a pair of parentheses around the number, it would be treated as a floating-point literal with a decimal point

Variable bit-lengths are problematic. If you were to put those binary numbers next to one another on an optical disc, for example, then you’d end up with a long stream of bits without clear boundaries between the characters

100000101011001110101111001011011112

One way of knowing how to interpret this information is to designate fixed-length bit patterns for all characters. In modern computing, the smallest unit of information, called an octet or a byte, comprises eight bits that can store 256 distinct values

Anda dapat mengisi poin kode biner Anda dengan angka nol di depan untuk menyatakannya dalam satuan byte

CharacterDecimal Code PointBinary Code Point€83641000100000 101011002u1171000000000 011101012r1141000000000 011100102o1111000000000 011011112

Sekarang setiap karakter membutuhkan dua byte, atau 16 bit. In total, your original text almost doubled in size, but at least it’s encoded reliably

You can use Huffman coding to find unambiguous bit patterns for every character in a particular text or use a more suitable character encoding. For example, to save space, UTF-8 intentionally favors Latin letters over symbols that you’re less likely to find in an English text

>>>

>>> len("€uro".encode("utf-8"))
6

Encoded according to the UTF-8 standard, the entire text takes six bytes. Since UTF-8 is a superset of ASCII, the letters

>>> (42).bit_length()
6
22,
>>> (42).bit_length()
6
23, and
>>> (42).bit_length()
6
24 occupy one byte each, whereas the euro symbol takes three bytes in this encoding

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1

Other types of information can be digitized similarly to text. Raster images are made of pixels, with every pixel having channels that represent color intensities as numbers. Sound waveforms contain numbers corresponding to air pressure at a given sampling interval. Three-dimensional models are built from geometric shapes defined by their vertices, and so forth

At the end of the day, everything is a number

Remove ads

Bitwise Logical Operators

You can use bitwise operators to perform on individual bits. That’s analogous to using logical operators such as

>>> (42).bit_length()
6
25,
>>> (42).bit_length()
6
26, and
>>> (42).bit_length()
6
27, but on a bit level. The similarities between bitwise and logical operators go beyond that

It’s possible to evaluate Boolean expressions with bitwise operators instead of logical operators, but such overuse is generally discouraged. If you’re interested in the details, then you can expand the box below to find out more

Evaluating Boolean Expressions With Bitwise OperatorsShow/Hide

The ordinary way of specifying compound Boolean expressions in Python is to use the logical operators that connect adjacent predicates, like this

if age >= 18 and not is_self_excluded:
    print("You can gamble")

Here, you check if the user is at least eighteen years old and if they haven’t opted out of gambling. You can rewrite that condition using bitwise operators

if age >= 18 & ~is_self_excluded:
    print("You can gamble")

Although this expression is syntactically correct, there are a few problems with it. First, it’s arguably less readable. Second, it doesn’t work as expected for all groups of data. Anda dapat mendemonstrasikannya dengan memilih nilai operan tertentu

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
_

Ekspresi yang dibuat dari operator bitwise dievaluasi menjadi

>>> (42).bit_length()
6
28, sedangkan ekspresi yang sama dibangun dari operator logis dievaluasi menjadi
>>> (42).bit_length()
6
29. Itu karena operator bitwise mengambil alih operator pembanding, mengubah cara seluruh ekspresi ditafsirkan

>>>

>>> age >= (18 & ~is_self_excluded)
True
_

Seolah-olah seseorang meletakkan tanda kurung implisit di sekitar operan yang salah. Untuk memperbaikinya, Anda dapat menempatkan tanda kurung eksplisit, yang akan menerapkan urutan evaluasi yang benar

>>> ________0______

Namun, Anda tidak lagi mendapatkan hasil Boolean. Operator bitwise Python dirancang terutama untuk bekerja dengan bilangan bulat, sehingga operan mereka secara otomatis dicor jika diperlukan. Ini mungkin tidak selalu memungkinkan

Meskipun Anda dapat menggunakan bilangan bulat yang benar dan salah dalam konteks Boolean, ini adalah antipattern yang dikenal yang dapat menghabiskan waktu berjam-jam untuk debugging yang tidak perlu. Anda lebih baik mengikuti Zen of Python untuk menyelamatkan diri dari masalah

Last but not least, Anda mungkin sengaja ingin menggunakan operator bitwise untuk menonaktifkan evaluasi hubung singkat dari ekspresi Boolean. Ekspresi menggunakan operator logis dievaluasi dengan malas dari kiri ke kanan. In other words, the evaluation stops as soon as the result of the entire expression is known

>>>

>>> 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

In the second example, the right operand isn’t called at all because the value of the entire expression has already been determined by the value of the left operand. No matter what the right operand is, it won’t affect the result, so there’s no point in calling it unless you rely on side effects

There are idioms, such as falling back to a default value, that take advantage of this peculiarity

>>>

>>> (42).bit_length()
6
0

A Boolean expression takes the value of the last evaluated operand. The operand becomes truthy or falsy inside the expression but retains its original type and value afterward. In particular, a positive integer on the left gets propagated, while a zero gets discarded

Unlike their logical counterparts, bitwise operators are evaluated eagerly

>>>

>>> (42).bit_length()
6
1

Even though knowing the left operand is sufficient to determine the value of the entire expression, all operands are always evaluated unconditionally

Unless you have a strong reason and know what you’re doing, you should use bitwise operators only for controlling bits. It’s too easy to get it wrong otherwise. In most cases, you’ll want to pass integers as arguments to the bitwise operators

Sedikit demi sedikit DAN

The bitwise AND operator (

>>> 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) performs logical conjunction on the corresponding bits of its operands. For each pair of bits occupying the same position in the two numbers, it returns a one only when both bits are switched on

Apa biner di python?

The resulting bit pattern is an intersection of the operator’s arguments. It has two bits turned on in the positions where both operands are ones. In all other places, at least one of the inputs has a zero bit

Arithmetically, this is equivalent to a product of two bit values. You can calculate the bitwise AND of numbers a and b by multiplying their bits at every index i

Apa biner di python?

Here’s a concrete example

ExpressionBinary ValueDecimal Value

>>> (42).bit_length()
6
3110011100215610
>>> (42).bit_length()
6
3211010025210
>>> 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

A one multiplied by one gives one, but anything multiplied by zero will always result in zero. Alternatively, you can take the of the two bits in each pair. Notice that when operands have unequal bit-lengths, the shorter one is automatically padded with zeros to the left

Bitwise OR

The bitwise OR operator (

>>> 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) performs logical disjunction. For each corresponding pair of bits, it returns a one if at least one of them is switched on

Apa biner di python?

The resulting bit pattern is a union of the operator’s arguments. It has five bits turned on where either of the operands has a one. Only a combination of two zeros gives a zero in the final output

The arithmetic behind it is a combination of a sum and a product of the bit values. To calculate the bitwise OR of numbers a and b, you need to apply the following formula to their bits at every index i

Apa biner di python?

Here’s a tangible example

ExpressionBinary ValueDecimal Value

>>> (42).bit_length()
6
3110011100215610
>>> (42).bit_length()
6
3211010025210
>>> 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

It’s almost like a sum of two bits but clamped at the higher end so that it never exceeds the value of one. You could also take the of the two bits in each pair to get the same result

Remove ads

Bitwise XOR

Unlike bitwise , , and , the bitwise XOR operator (

>>> 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) doesn’t have a logical counterpart in Python. However, you can simulate it by building on top of the existing operators

>>> (42).bit_length()
6
2

It evaluates two mutually exclusive conditions and tells you whether exactly one of them is met. For example, a person can be either a minor or an adult, but not both at the same time. Conversely, it’s not possible for a person to be neither a minor nor an adult. The choice is mandatory

The name XOR stands for “exclusive or” since it performs exclusive disjunction on the bit pairs. In other words, every bit pair must contain opposing bit values to produce a one

Apa biner di python?

Visually, it’s a symmetric difference of the operator’s arguments. There are three bits switched on in the result where both numbers have different bit values. Bits in the remaining positions cancel out because they’re the same

Similarly to the bitwise OR operator, the arithmetic of XOR involves a sum. However, while the bitwise OR clamps values at one, the XOR operator wraps them around with a sum modulo two

Apa biner di python?

Modulo is a function of two numbers—the dividend and the divisor—that performs a division and returns its remainder. In Python, there’s a built-in modulo operator denoted with the percent sign (

>>> (42).bit_length()
6
39)

Once again, you can confirm the formula by looking at an example

ExpressionBinary ValueDecimal Value

>>> (42).bit_length()
6
3110011100215610
>>> (42).bit_length()
6
3211010025210
>>> 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

The sum of two zeros or two ones yields a whole number when divided by two, so the result has a remainder of zero. However, when you divide the sum of two different bit values by two, you get a fraction with a remainder of one. A more straightforward formula for the XOR operator is the difference between the maximum and the minimum of both bits in each pair

Bitwise NOT

The last of the bitwise logical operators is the bitwise NOT operator (

>>> 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), which expects just one argument, making it the only unary bitwise operator. It performs logical negation on a given number by flipping all of its bits

Apa biner di python?

The inverted bits are a complement to one, which turns zeros into ones and ones into zeros. It can be expressed arithmetically as the subtraction of individual bit values from one

Apa biner di python?

Here’s an example showing one of the numbers used before

ExpressionBinary ValueDecimal Value

>>> (42).bit_length()
6
3110011100215610
>>> 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

While the bitwise NOT operator seems to be the most straightforward of them all, you need to exercise extreme caution when using it in Python. Everything you’ve read so far is based on the assumption that numbers are represented with unsigned integers

Note. Unsigned data types don’t let you store negative numbers such as -273 because there’s no space for a sign in a regular bit pattern. Trying to do so would result in a compilation error, a runtime exception, or an integer overflow depending on the language used

Although there are ways to simulate , Python doesn’t support them natively. That means all numbers have an implicit sign attached to them whether you specify one or not. Ini menunjukkan ketika Anda melakukan bitwise BUKAN dari angka apa pun

>>>

>>> (42).bit_length()
6
3

Instead of the expected 9910, you get a negative value. The reason for this will become clear once you learn about the various . For now, the quick-fix solution is to take advantage of the bitwise AND operator

>>>

>>> (42).bit_length()
6
4

That’s a perfect example of a , which you’ll explore in one of the upcoming sections

Remove ads

Bitwise Shift Operators

Bitwise shift operators are another kind of tool for bit manipulation. Mereka membiarkan Anda memindahkan bit, yang akan berguna untuk membuat bitmask nanti. In the past, they were often used to improve the speed of certain mathematical operations

Left Shift

Operator geser kiri 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
_9) memindahkan bit operan pertamanya ke kiri dengan jumlah tempat yang ditentukan dalam operan keduanya. Ini juga menangani penyisipan bit nol yang cukup untuk mengisi celah yang muncul di tepi kanan pola bit baru

Apa biner di python?

Menggeser satu bit ke kiri satu tempat akan menggandakan nilainya. Misalnya, alih-alih dua, bit akan menunjukkan empat setelah pergeseran. Memindahkannya dua tempat ke kiri akan melipatgandakan nilai yang dihasilkan. Saat Anda menjumlahkan semua bit dalam angka tertentu, Anda akan melihat bahwa angka itu juga menjadi dua kali lipat dengan setiap tempat bergeser

ExpressionBinary ValueDecimal Value

>>> (42).bit_length()
6
3110011123910
>>> (42).bit_length()
6
48100111027810
>>> (42).bit_length()
6
4910011100215610
>>> (42).bit_length()
6
50100111000231210

Secara umum, menggeser bit ke kiri sama dengan mengalikan angka dengan pangkat dua, dengan eksponen sama dengan jumlah tempat yang digeser

Apa biner di python?

Pergeseran ke kiri dulunya merupakan teknik pengoptimalan yang populer karena pergeseran bit adalah instruksi tunggal dan lebih murah untuk dihitung daripada eksponen atau perkalian. Namun hari ini, kompiler dan juru bahasa, termasuk Python, cukup mampu mengoptimalkan kode Anda di belakang layar

Catatan. Jangan gunakan operator bit shift sebagai sarana pengoptimalan prematur dengan Python. Anda tidak akan melihat perbedaan dalam kecepatan eksekusi, tetapi Anda pasti akan membuat kode Anda kurang mudah dibaca

Di atas kertas, pola bit yang dihasilkan dari pergeseran kiri menjadi lebih panjang sebanyak Anda menggesernya. Itu juga berlaku untuk Python secara umum karena cara menangani bilangan bulat. Namun, dalam sebagian besar kasus praktis, Anda ingin membatasi panjang pola bit menjadi kelipatan delapan, yang merupakan panjang byte standar

Misalnya, jika Anda bekerja dengan satu byte, maka menggesernya ke kiri akan membuang semua bit yang melampaui batas kirinya.

Apa biner di python?

Ini seperti melihat aliran bit yang tidak terbatas melalui jendela dengan panjang tetap. Ada beberapa trik yang memungkinkan Anda melakukan ini dengan Python. Misalnya, Anda dapat menerapkan a dengan operator AND bitwise

>>>

>>> (42).bit_length()
6
5

Menggeser 3910 sebanyak tiga tempat ke kiri mengembalikan angka yang lebih tinggi dari nilai maksimum yang dapat Anda simpan pada satu byte. Dibutuhkan sembilan bit, sedangkan satu byte hanya memiliki delapan. Untuk memotong satu bit ekstra di sebelah kiri, Anda dapat menerapkan bitmask dengan nilai yang sesuai. Jika Anda ingin menyimpan lebih banyak atau lebih sedikit bit, maka Anda harus mengubah nilai topengnya

Pergeseran Kanan

Operator bitwise shift kanan (

>>> (42).bit_length()
6
01) analog dengan yang kiri, tetapi alih-alih memindahkan bit ke kiri, ia mendorongnya ke kanan dengan jumlah tempat yang ditentukan. Bit paling kanan selalu dijatuhkan

Apa biner di python?

Setiap kali Anda bergeser sedikit ke kanan dengan satu posisi, Anda membagi dua nilai dasarnya. Memindahkan bit yang sama dengan dua tempat ke kanan menghasilkan seperempat dari nilai aslinya, dan seterusnya. Saat Anda menjumlahkan semua bit individual, Anda akan melihat bahwa aturan yang sama berlaku untuk angka yang diwakilinya

ExpressionBinary ValueDecimal Value

>>> (42).bit_length()
6
3110011101215710
>>> (42).bit_length()
6
53100111027810
>>> (42).bit_length()
6
5410011123910
>>> (42).bit_length()
6
551001121910

Membagi dua angka ganjil seperti 15710 akan menghasilkan pecahan. Untuk menghilangkannya, operator shift kanan otomatis hasilnya. Ini hampir sama dengan pembagian lantai dengan pangkat dua

Apa biner di python?

Sekali lagi, eksponen sesuai dengan jumlah tempat yang digeser ke kanan. Di Python, Anda dapat memanfaatkan operator khusus untuk melakukan pembagian lantai

>>>

>>> (42).bit_length()
6
6

Operator bitwise shift kanan dan operator pembagian lantai keduanya bekerja dengan cara yang sama, bahkan untuk bilangan negatif. Namun, pembagian lantai memungkinkan Anda memilih pembagi apa pun dan bukan hanya pangkat dua. Using the bitwise right shift was a common way of improving the performance of some arithmetic divisions

Catatan. Anda mungkin bertanya-tanya apa yang terjadi jika Anda kehabisan bit untuk digeser. Misalnya, ketika Anda mencoba mendorong lebih banyak tempat daripada jumlah bit

>>> ________11______7

Setelah tidak ada lagi bit yang diaktifkan, Anda terjebak dengan nilai nol. Nol dibagi dengan apapun akan selalu menghasilkan nol. Namun, hal-hal menjadi lebih rumit ketika Anda menggeser angka negatif dengan benar karena bit tanda implisit menghalangi

>>> ________11______8

Aturan praktisnya adalah, apa pun tandanya, hasilnya akan sama dengan pembagian lantai dengan pangkat dua. Dasar pecahan negatif kecil selalu minus satu, dan itulah yang akan Anda dapatkan. Baca terus untuk penjelasan yang lebih rinci

Sama seperti operator shift kiri, pola bit berubah ukurannya setelah shift kanan. Saat memindahkan bit ke kanan membuat urutan biner lebih pendek, biasanya tidak masalah karena Anda dapat meletakkan angka nol di depan urutan bit sebanyak yang Anda suka tanpa mengubah nilainya. Misalnya, 1012 sama dengan 01012, demikian juga 000001012, asalkan Anda berurusan dengan bilangan nonnegatif

Terkadang Anda ingin mempertahankan panjang bit tertentu setelah melakukan pergeseran yang benar untuk menyelaraskannya dengan nilai lain atau agar pas di suatu tempat. Anda dapat melakukannya dengan menerapkan bitmask

Apa biner di python?

Itu hanya mengukir bit yang Anda minati dan mengisi pola bit dengan nol di depan jika perlu

Penanganan bilangan negatif dalam Python sedikit berbeda dari pendekatan tradisional untuk pengalihan bitwise. Di bagian selanjutnya, Anda akan memeriksanya lebih detail

Remove ads

Pergeseran Aritmatika vs Logis

Anda selanjutnya dapat mengkategorikan operator pergeseran bitwise sebagai operator pergeseran aritmatika dan logis. Sementara Python hanya memungkinkan Anda melakukan pergeseran aritmatika, ada baiknya untuk mengetahui bagaimana bahasa pemrograman lain mengimplementasikan operator pergeseran bitwise untuk menghindari kebingungan dan kejutan.

Perbedaan ini berasal dari cara mereka menangani bit tanda, yang biasanya terletak di tepi paling kiri dari urutan biner bertanda. Dalam praktiknya, ini hanya relevan untuk operator shift kanan, yang dapat menyebabkan angka membalik tandanya, yang menyebabkan luapan bilangan bulat

Catatan. Java dan JavaScript, misalnya, membedakan operator pergeseran kanan logis dengan tambahan tanda lebih besar dari (

>>> (42).bit_length()
6
03). Karena operator shift kiri berperilaku secara konsisten di kedua jenis shift, bahasa ini tidak menentukan pasangan shift kiri yang logis

Secara konvensional, bit tanda yang dihidupkan menunjukkan angka negatif, yang membantu menjaga sifat aritmatika dari deret biner

Nilai DesimalSigned Binary ValueSign BitSignMeaning-100101001110021-Bilangan negatif28100001110020+Bilangan positif atau nol

Melihat dari kiri pada dua urutan biner ini, Anda dapat melihat bahwa bit pertama mereka membawa informasi tanda, sedangkan bagian sisanya terdiri dari bit magnitudo, yang sama untuk kedua angka.

Catatan. Nilai desimal spesifik akan bergantung pada bagaimana Anda memutuskan untuk menyatakan angka bertanda dalam biner. Ini bervariasi antar bahasa dan menjadi lebih rumit dengan Python, jadi Anda dapat mengabaikannya untuk saat ini. Anda akan memiliki gambaran yang lebih baik setelah Anda masuk ke bagian di bawah ini

Pergeseran kanan logis, juga dikenal sebagai pergeseran kanan tanpa tanda atau pergeseran kanan pengisian-nol, memindahkan seluruh urutan biner, termasuk bit tanda, dan mengisi celah yang dihasilkan di sebelah kiri dengan nol

Apa biner di python?

Perhatikan bagaimana informasi tentang tanda nomor tersebut hilang. Terlepas dari tanda aslinya, itu akan selalu menghasilkan bilangan bulat nonnegatif karena bit tanda diganti dengan nol. Selama Anda tidak tertarik dengan nilai numerik, pergeseran logis ke kanan dapat berguna dalam memproses data biner tingkat rendah

Namun, karena bilangan biner bertanda biasanya disimpan pada urutan bit dengan panjang tetap di sebagian besar bahasa, ini dapat membuat hasilnya membungkus nilai ekstrem. Anda dapat melihat ini di alat Java Shell yang interaktif

>>> (42).bit_length()
6
_9

Angka yang dihasilkan mengubah tandanya dari negatif menjadi positif, tetapi juga meluap, berakhir sangat dekat dengan bilangan bulat maksimum Java

>>> len("€uro".encode("utf-8"))
6
_0

Angka ini mungkin tampak sewenang-wenang pada pandangan pertama, tetapi ini terkait langsung dengan jumlah bit yang dialokasikan Java untuk tipe data

>>> (42).bit_length()
6
57

>>> len("€uro".encode("utf-8"))
6
_1

Ini menggunakan 32 bit untuk menyimpan dalam representasi komplemen dua. Saat Anda mengeluarkan bit tanda, tersisa 31 bit, yang nilai desimal maksimumnya sama dengan 231 - 1, atau 214748364710

Python, di sisi lain, menyimpan bilangan bulat seolah-olah ada jumlah bit tak terbatas yang Anda inginkan. Konsekuensinya, operator shift kanan yang logis tidak akan terdefinisi dengan baik dalam Python murni, sehingga hilang dari bahasa. Anda masih bisa mensimulasikannya

Salah satu cara melakukannya adalah dengan memanfaatkan tipe data unsigned yang tersedia di C yang diekspos melalui modul

>>> (42).bit_length()
6
58 bawaan

>>>

>>> len("€uro".encode("utf-8"))
6
2

Mereka membiarkan Anda memasukkan angka negatif tetapi tidak melampirkan arti khusus apa pun pada bit tanda. Itu diperlakukan seperti bit besaran lainnya

Meskipun hanya ada beberapa tipe integer unsigned yang telah ditentukan sebelumnya di C, yang berbeda dalam panjang bit, Anda dapat membuat fungsi khusus di Python untuk menangani panjang bit yang sewenang-wenang

>>>

>>> len("€uro".encode("utf-8"))
6
3

Ini mengubah urutan bit yang ditandatangani menjadi yang tidak ditandatangani dan kemudian melakukan pergeseran kanan aritmatika biasa

Namun, karena urutan bit dalam Python tidak memiliki panjang yang tetap, mereka tidak benar-benar memiliki bit tanda. Selain itu, mereka tidak menggunakan representasi komplemen dua tradisional seperti di C atau Java. Untuk menguranginya, Anda dapat memanfaatkan operasi modulo, yang akan mempertahankan pola bit asli untuk bilangan bulat positif sambil membungkus bilangan negatif dengan tepat.

Pergeseran kanan aritmatika (

>>> (42).bit_length()
6
01), terkadang disebut operator pergeseran kanan bertanda, mempertahankan tanda angka dengan mereplikasi bit tandanya sebelum memindahkan bit ke kanan

Apa biner di python?

Dengan kata lain, ini mengisi celah di sebelah kiri dengan bit tanda apa pun. Dikombinasikan dengan representasi pelengkap dua biner bertanda, ini menghasilkan nilai yang benar secara aritmatika. Terlepas dari apakah angkanya positif atau negatif, pergeseran ke kanan aritmatika setara dengan pembagian lantai

Seperti yang akan Anda ketahui, Python tidak selalu menyimpan bilangan bulat dalam biner komplemen dua biasa. Alih-alih, ini mengikuti strategi adaptif khusus yang berfungsi seperti dengan jumlah bit yang tidak terbatas. Itu mengubah angka bolak-balik antara representasi internal mereka dan komplemen dua untuk meniru perilaku standar dari pergeseran aritmatika

Remove ads

Representasi Bilangan Biner

Anda telah mengalami secara langsung kurangnya tipe data unsigned di Python saat menggunakan negasi 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) dan operator shift kanan (
>>> (42).bit_length()
6
01). Anda telah melihat petunjuk tentang pendekatan penyimpanan yang tidak biasa, yang membuat penanganan angka negatif menjadi rumit. Untuk menggunakan operator bitwise secara efektif, Anda perlu mengetahui tentang berbagai representasi angka dalam biner

Bilangan bulat yang tidak ditandatangani

Dalam bahasa pemrograman seperti C, Anda memilih apakah akan menggunakan ragam bertanda atau tidak bertanda dari tipe numerik tertentu. Tipe data yang tidak ditandatangani lebih cocok jika Anda tahu pasti bahwa Anda tidak perlu berurusan dengan angka negatif. Dengan mengalokasikan satu bit ekstra itu, yang jika tidak berfungsi sebagai bit tanda, Anda secara praktis menggandakan rentang nilai yang tersedia

Itu juga membuat segalanya sedikit lebih aman dengan meningkatkan batas maksimum sebelum luapan terjadi. Namun, luapan hanya terjadi dengan panjang bit tetap, sehingga tidak relevan dengan Python, yang tidak memiliki batasan seperti itu

Cara tercepat untuk merasakan tipe numerik unsigned di Python adalah dengan menggunakan modul

>>> (42).bit_length()
6
58 yang disebutkan sebelumnya

>>>

>>> len("€uro".encode("utf-8"))
6
4

Karena tidak ada bit tanda dalam bilangan bulat seperti itu, semua bitnya mewakili besarnya angka. Melewati angka negatif memaksa Python untuk menginterpretasikan kembali pola bit seolah-olah hanya memiliki bit besaran

Integer yang ditandatangani

Tanda angka hanya memiliki dua status. Jika Anda mengabaikan nol sesaat, maka itu bisa menjadi positif atau negatif, yang diterjemahkan dengan baik ke sistem biner. Namun ada beberapa cara alternatif untuk merepresentasikan bilangan bulat bertanda dalam biner, masing-masing dengan kelebihan dan kekurangannya sendiri

Mungkin yang paling mudah adalah tanda-magnitudo, yang dibangun secara alami di atas bilangan bulat tak bertanda. Ketika urutan biner ditafsirkan sebagai besaran tanda, bit tersebut memainkan peran sebagai bit tanda, sedangkan bit lainnya bekerja sama seperti biasanya.

Urutan BinerTanda-Magnitudo NilaiUnsigned Value00101010242104210101010102-421017010

Nol pada bit paling kiri menunjukkan angka positif (

>>> (42).bit_length()
6
63), dan satu menunjukkan angka negatif (
>>> (42).bit_length()
6
64). Perhatikan bahwa bit tanda tidak berkontribusi pada nilai absolut angka dalam representasi magnitudo tanda. Itu ada hanya untuk membiarkan Anda membalik tanda bit yang tersisa

Mengapa sedikit paling kiri?

Itu membuat pengindeksan bit utuh, yang, pada gilirannya, membantu menjaga kompatibilitas mundur dari bobot bit yang digunakan untuk menghitung nilai desimal dari urutan biner. Namun, tidak semua tentang magnitudo tanda begitu hebat

Catatan. Representasi biner dari bilangan bulat yang ditandatangani hanya masuk akal pada urutan bit dengan panjang tetap. Jika tidak, Anda tidak dapat mengetahui di mana bit tanda itu berada. Namun, dalam Python, Anda dapat merepresentasikan bilangan bulat dengan bit sebanyak yang Anda suka

>>>

>>> len("€uro".encode("utf-8"))
6
5

Apakah itu empat atau delapan bit tanda akan selalu ditemukan di posisi paling kiri

Rentang nilai yang dapat Anda simpan dalam pola bit tanda-magnitudo bersifat simetris. Tapi itu juga berarti bahwa Anda berakhir dengan dua cara untuk menyampaikan nol

Urutan BinerNilai Magnitudo TandaNilai Tidak Bertanda000000002+010010100000002-01012810

Nol secara teknis tidak memiliki tanda, tetapi tidak ada cara untuk tidak menyertakannya dalam besaran tanda. Meskipun memiliki angka nol yang ambigu tidak ideal dalam banyak kasus, itu bukanlah bagian terburuk dari cerita. Kelemahan terbesar dari metode ini adalah aritmatika biner yang rumit

Saat Anda menerapkan aritmatika biner standar ke angka yang disimpan dalam magnitudo tanda, ini mungkin tidak memberi Anda hasil yang diharapkan. Misalnya, menjumlahkan dua bilangan yang sama besar tetapi berlawanan tanda tidak akan menghilangkannya

ExpressionBinary SequenceSign-Magnitude Value

>>> (42).bit_length()
6
310010101024210
>>> (42).bit_length()
6
32101010102-4210
>>> (42).bit_length()
6
67110101002-8410

Jumlah 42 dan -42 tidak menghasilkan nol. Juga, bit carryover kadang-kadang dapat merambat dari magnitudo ke bit tanda, membalikkan tanda dan menghasilkan hasil yang tidak diharapkan.

Untuk mengatasi masalah ini, beberapa komputer awal menggunakan representasi komplemen seseorang. Idenya adalah mengubah cara bilangan desimal dipetakan ke deret biner tertentu sehingga dapat dijumlahkan dengan benar. Untuk menyelami lebih dalam pelengkap seseorang, Anda dapat memperluas bagian di bawah ini

Pelengkap SeseorangTampilkan/Sembunyikan

In one’s complement, positive numbers are the same as in sign-magnitude, but negative numbers are obtained by flipping the positive number’s bits using a bitwise NOT

Positive SequenceNegative SequenceMagnitude Value000000002111111112±010000000012111111102±110000000102111111012±210⋮⋮⋮011111112100000002±12710

This preserves the original meaning of the sign bit, so positive numbers still begin with a binary zero, while negative ones start with a binary one. Likewise, the range of values remains symmetrical and continues to have two ways to represent zero. However, the binary sequences of negative numbers in one’s complement are arranged in reverse order as compared to sign-magnitude

One’s ComplementSign-MagnitudeDecimal Value111111112100000002-010111111102100000012-110111111012100000102-210↓↑⋮100000102111111012-12510100000012111111102-12610100000002111111112-12710

Thanks to that, you can now add two numbers more reliably because the sign bit doesn’t need special treatment. If a carryover originates from the sign bit, it’s fed back at the right edge of the binary sequence instead of just being dropped. This ensures the correct result

Nevertheless, modern computers don’t use one’s complement to represent integers because there’s an even better way called two’s complement. By applying a small modification, you can eliminate double zero and simplify the binary arithmetic in one go. To explore two’s complement in more detail, you can expand the section below

Two's ComplementShow/Hide

When finding bit sequences of negative values in two’s complement, the trick is to add one to the result after negating the bits

Positive SequenceOne’s Complement (NOT)Two’s Complement (NOT+1)000000002111111112000000002000000012111111102111111112000000102111111012111111102⋮⋮⋮011111112100000002100000012

This pushes the bit sequences of negative numbers down by one place, eliminating the notorious minus zero. A more useful minus one will take over its bit pattern instead

As a side effect, the range of available values in two’s complement becomes asymmetrical, with a lower bound that’s a power of two and an odd upper bound. For example, an 8-bit signed integer will let you store numbers from -12810 to 12710 in two’s complement

Two’s ComplementOne’s ComplementDecimal Value100000002N/A-12810100000012100000002-12710100000102100000012-12610⋮⋮⋮111111102111111012-210111111112111111102-110N/A111111112-010000000002000000002010000000012000000012110000000102000000102210⋮⋮⋮01111111201111111212710

Another way to put it is that the most significant bit carries both the sign and part of the number magnitude

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

Notice the minus sign next to the leftmost bit weight. Deriving a decimal value from a binary sequence like that is only a matter of adding appropriate columns. For example, the value of 110101102 in 8-bit two’s complement representation is the same as the sum. -12810 + 6410 + 1610 + 410 + 210 = -4210

With the two’s complement representation, you no longer need to worry about the carryover bit unless you want to use it as an overflow detection mechanism, which is kind of neat

There are a few other variants of signed number representations, but they’re not as popular

Remove ads

Floating-Point Numbers

The IEEE 754 standard defines a binary representation for real numbers consisting of the sign, exponent, and mantissa bits. Without getting into too many technical details, you can think of it as the scientific notation for binary numbers. The decimal point “floats” around to accommodate a varying number of significant figures, except it’s a binary point

Two data types conforming to that standard are widely supported

  1. Single precision. 1 sign bit, 8 exponent bits, 23 mantissa bits
  2. Double precision. 1 sign bit, 11 exponent bits, 52 mantissa bits

Python’s

>>> (42).bit_length()
6
68 data type is equivalent to the double-precision type. Note that some applications require more or fewer bits. For example, the OpenEXR image format takes advantage of half precision to represent pixels with a high dynamic range of colors at a reasonable file size

The number Pi (π) has the following binary representation in single precision when rounded to five decimal places

SignExponentMantissa02100000002. 100100100001111110100002

The sign bit works just like with integers, so zero denotes a positive number. For the exponent and mantissa, however, different rules can apply depending on a few edge cases

First, you need to convert them from binary to the decimal form

  • Exponent. 12810
  • Mantissa. 2-1 + 2-4 + … + 2-19 = 29926110/52428810 ≈ 0. 57079510

The exponent is stored as an unsigned integer, but to account for negative values, it usually has a bias equal to 12710 in single precision. You need to subtract it to recover the actual exponent

Mantissa bits represent a fraction, so they correspond to negative powers of two. Additionally, you need to add one to the mantissa because it assumes an implicit leading bit before the radix point in this particular case

Putting it all together, you arrive at the following formula to convert a floating-point binary number into a decimal one

Apa biner di python?

When you substitute the variables for the actual values in the example above, you’ll be able to decipher the bit pattern of a floating-point number stored in single precision

Apa biner di python?

There it is, granted that Pi has been rounded to five decimal places. You’ll learn how to later on

Bilangan Titik Tetap

While floating-point numbers are a good fit for engineering purposes, they fail in monetary calculations due to their limited precision. For example, some numbers with a finite representation in decimal notation have only an infinite representation in binary. That often results in a rounding error, which can accumulate over time

>>>

>>> len("€uro".encode("utf-8"))
6
6

In such cases, you’re better off using Python’s module, which implements fixed-point arithmetic and lets you specify where to put the decimal point on a given bit-length. For example, you can tell it how many digits you want to preserve

>>>

>>> len("€uro".encode("utf-8"))
6
7

However, it includes all digits, not just the fractional ones

Note. If you’re working with rational numbers, then you might be interested in checking out the

>>> (42).bit_length()
6
70 module, which is part of Python’s standard library

If you can’t or don’t want to use a fixed-point data type, a straightforward way to reliably store currency values is to scale the amounts to the smallest unit, such as cents, and represent them with integers

Remove ads

Integers in Python

In the old days of programming, computer memory was at a premium. Therefore, languages would give you pretty granular control over how many bytes to allocate for your data. Let’s take a quick peek at a few integer types from C as an example

TypeSizeMinimum ValueMaximum Value

>>> (42).bit_length()
6
711 byte-128127
>>> (42).bit_length()
6
722 bytes-32,76832,767
>>> (42).bit_length()
6
734 bytes-2,147,483,6482,147,483,647
>>> (42).bit_length()
6
748 bytes-9,223,372,036,854,775,8089,223,372,036,854,775,807

These values might vary from platform to platform. However, such an abundance of numeric types allows you to arrange data in memory compactly. Remember that these don’t even include unsigned types

On the other end of the spectrum are languages such as JavaScript, which have just one numeric type to rule them all. While this is less confusing for beginning programmers, it comes at the price of increased memory consumption, reduced processing efficiency, and decreased precision

When talking about bitwise operators, it’s essential to understand how Python handles integer numbers. Lagi pula, Anda akan menggunakan operator ini terutama untuk bekerja dengan bilangan bulat. Ada beberapa representasi bilangan bulat yang sangat berbeda di Python yang bergantung pada nilainya

Bilangan Bulat Diinternir

Di CPython, bilangan bulat yang sangat kecil antara -510 dan 25610 berada dalam cache global untuk mendapatkan beberapa kinerja karena angka dalam rentang tersebut biasanya digunakan. Dalam praktiknya, setiap kali Anda merujuk ke salah satu dari nilai tersebut, yang merupakan lajang yang dibuat saat startup juru bahasa, Python akan selalu memberikan contoh yang sama

>>> ________35______8

Kedua variabel memiliki kesamaan karena mengacu pada objek yang sama persis di memori. Itu khas dari tipe referensi tetapi bukan nilai yang tidak dapat diubah seperti bilangan bulat. Namun, saat Anda melampaui rentang nilai cache tersebut, Python akan mulai membuat salinan yang berbeda selama penugasan variabel

>>>

>>> len("€uro".encode("utf-8"))
6
9

Meskipun memiliki nilai yang sama, variabel-variabel ini menunjuk ke objek yang terpisah sekarang. Tapi jangan biarkan itu membodohi Anda. Python sesekali akan masuk dan mengoptimalkan kode Anda di belakang layar. Misalnya, ini akan meng-cache nomor yang muncul di baris yang sama berkali-kali terlepas dari nilainya

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
0

Variabel

>>> (42).bit_length()
6
31 dan
>>> (42).bit_length()
6
32 adalah objek independen karena mereka berada di lokasi memori yang berbeda, sedangkan angka yang digunakan secara harfiah di
>>> (42).bit_length()
6
77 sebenarnya adalah objek yang sama

Catatan. Magang adalah detail implementasi dari juru bahasa CPython, yang mungkin berubah di versi mendatang, jadi jangan mengandalkannya di program Anda

Menariknya, ada mekanisme interning string serupa di Python, yang berlaku untuk teks pendek yang hanya terdiri dari huruf ASCII. Ini membantu mempercepat pencarian kamus dengan memungkinkan kuncinya dibandingkan dengan alamat memori, atau pointer C, bukan dengan karakter string individual

Bilangan Bulat Presisi Tetap

Bilangan bulat yang kemungkinan besar Anda temukan di Python akan memanfaatkan tipe data C

>>> (42).bit_length()
6
78. Mereka menggunakan representasi biner komplemen dua klasik pada jumlah bit yang tetap. Panjang bit yang tepat akan bergantung pada platform perangkat keras, sistem operasi, dan versi juru bahasa Python Anda

Komputer modern biasanya menggunakan arsitektur 64-bit, jadi ini akan diterjemahkan menjadi angka desimal antara -263 dan 263 - 1. Anda dapat memeriksa nilai maksimum bilangan bulat presisi tetap di Python dengan cara berikut

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
1

Itu besar. Kira-kira 9 juta kali jumlah bintang di galaksi kita, jadi cukup untuk penggunaan sehari-hari. Sementara nilai maksimum yang bisa Anda keluarkan dari tipe

>>> (42).bit_length()
6
79 di C bahkan lebih besar, di urutan 1019, bilangan bulat di Python tidak memiliki batas teoretis. Untuk memungkinkan ini, angka yang tidak sesuai dengan urutan bit dengan panjang tetap disimpan secara berbeda di memori

Remove ads

Bilangan Bulat Presisi Sewenang-wenang

Apakah Anda ingat lagu K-pop populer "Gangnam Style" yang menjadi hit di seluruh dunia pada tahun 2012? . Segera setelah itu, begitu banyak orang yang menonton video tersebut sehingga membuat view counter meluap. YouTube tidak punya pilihan selain memutakhirkan penghitung mereka dari bilangan bulat bertanda 32-bit menjadi bilangan bulat 64-bit

Itu mungkin memberi banyak ruang kepala untuk penghitung tampilan, tetapi ada jumlah yang lebih besar lagi yang tidak biasa dalam kehidupan nyata, terutama di dunia ilmiah. Meskipun demikian, Python dapat menanganinya dengan mudah

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
2

Angka ini memiliki lima puluh dua angka desimal. Diperlukan setidaknya 170 bit untuk merepresentasikannya dalam biner dengan pendekatan tradisional

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
3

Karena mereka jauh di atas batas yang ditawarkan oleh tipe C mana pun, bilangan astronomi semacam itu diubah menjadi sistem posisi magnitudo tanda, yang basisnya adalah 230. Ya, Anda membacanya dengan benar. Sedangkan Anda memiliki sepuluh jari, Python memiliki lebih dari satu miliar

Sekali lagi, ini dapat bervariasi tergantung pada platform yang Anda gunakan saat ini. Jika ragu, Anda dapat memeriksa ulang

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
4

Ini akan memberi tahu Anda berapa banyak bit yang digunakan per digit dan berapa ukuran dalam byte dari struktur C yang mendasarinya. To get the same in Python 2, you’d refer to the

>>> (42).bit_length()
6
80 attribute instead

Sementara konversi antara bilangan bulat presisi tetap dan sewenang-wenang ini dilakukan dengan mulus di bawah tenda di Python 3, ada saat ketika hal-hal menjadi lebih eksplisit. Untuk informasi lebih lanjut, Anda dapat memperluas kotak di bawah ini

>>> (42).bit_length()
6
73 dan
>>> (42).bit_length()
6
74 dengan Python 2Tampilkan/Sembunyikan

Di masa lalu, Python secara eksplisit mendefinisikan dua tipe integer yang berbeda

  1. Bilangan bulat biasa
  2. Bilangan bulat panjang

The first one was modeled after the C

>>> (42).bit_length()
6
78 type, which typically occupied 32 or 64 bits and offered a limited range of values

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
5

Untuk angka yang lebih besar, Anda seharusnya menggunakan tipe kedua yang tidak memiliki batasan. Python akan secara otomatis mempromosikan bilangan bulat biasa menjadi bilangan panjang jika diperlukan

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
6

Fitur ini mencegah kesalahan integer overflow. Notice the letter

>>> (42).bit_length()
6
84 at the end of a literal, which could be used to enforce the given type by hand

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
7

Eventually, both types were unified so that you wouldn’t have to think about it anymore

Representasi seperti itu menghilangkan kesalahan integer overflow dan memberikan ilusi panjang bit tak terbatas, tetapi membutuhkan lebih banyak memori secara signifikan. Selain itu, melakukan aritmatika bignum lebih lambat dibandingkan dengan presisi tetap karena tidak dapat berjalan langsung di perangkat keras tanpa lapisan perantara emulasi

Tantangan lain adalah mempertahankan perilaku operator bitwise yang konsisten di seluruh tipe bilangan bulat alternatif, yang sangat penting dalam menangani bit tanda. Ingatlah bahwa bilangan bulat presisi tetap di Python menggunakan representasi komplemen dua standar dari C, sedangkan bilangan bulat besar menggunakan magnitudo tanda

Untuk mengurangi perbedaan itu, Python akan melakukan konversi biner yang diperlukan untuk Anda. Itu mungkin mengubah cara angka direpresentasikan sebelum dan sesudah menerapkan operator bitwise. Inilah komentar yang relevan dari kode sumber CPython, yang menjelaskan hal ini lebih detail

Operasi bitwise untuk angka negatif beroperasi seolah-olah pada representasi komplemen dua. So convert arguments from sign-magnitude to two’s complement, and convert the result back to sign-magnitude at the end. ()

Dengan kata lain, angka negatif diperlakukan sebagai urutan bit pelengkap dua saat Anda menerapkan operator bitwise padanya, meskipun hasilnya akan disajikan kepada Anda dalam bentuk besaran tanda. Ada beberapa cara untuk dan beberapa tipe unsigned di Python

Bit String dengan Python

Anda dipersilakan untuk menggunakan pena dan kertas di sepanjang sisa artikel ini. Bahkan bisa berfungsi sebagai latihan yang bagus. Namun, pada titik tertentu, Anda ingin memverifikasi apakah urutan biner atau string bit Anda sesuai dengan angka yang diharapkan di Python. Begini caranya

Mengubah >>> (42).bit_length() 6 _73 menjadi Biner

Untuk mengungkapkan bit yang membentuk bilangan bulat dengan Python, Anda dapat mencetak literal string yang diformat, yang secara opsional memungkinkan Anda menentukan jumlah nol di depan untuk ditampilkan

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
8

Alternatifnya, Anda dapat memanggil

>>> (42).bit_length()
6
_86 dengan nomor tersebut sebagai argumen

>>>

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
9

Fungsi bawaan global ini mengembalikan string yang terdiri dari literal biner, yang dimulai dengan awalan

>>> (42).bit_length()
6
87 dan diikuti dengan satu dan nol. Itu selalu menunjukkan jumlah digit minimum tanpa nol di depan

Anda juga dapat menggunakan literal seperti itu dalam kode Anda

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
0

Literal integer lain yang tersedia di Python adalah yang heksadesimal dan oktal, yang dapat Anda peroleh masing-masing dengan fungsi ________11______88 dan

>>> (42).bit_length()
6
89

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
1

Perhatikan bagaimana sistem heksadesimal, yang berbasis enam belas, memanfaatkan huruf

>>> (42).bit_length()
6
90 hingga
>>> (42).bit_length()
6
91 untuk menambah himpunan digit yang tersedia. The octal literals in other programming languages are usually prefixed with plain zero, which might be confusing. Python explicitly forbids such literals to avoid making a mistake

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
2

You can express the same value in different ways using any of the mentioned integer literals

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
3

Choose the one that makes the most sense in context. For example, it’s customary to express with hexadecimal notation. On the other hand, the octal literal is rarely seen these days

All numeric literals in Python are case insensitive, so you can prefix them with either lowercase or uppercase letters

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
4

This also applies to floating-point number literals that use scientific notation as well as complex number literals

Remove ads

Converting Binary to >>> (42).bit_length() 6 73

Once you have your bit string ready, you can get its decimal representation by taking advantage of a binary literal

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
5

This is a quick way to do the conversion while working inside the interactive Python interpreter. Unfortunately, it won’t let you convert bit sequences synthesized at runtime because all literals need to be hard-coded in the source code

Note. You might be tempted to evaluate Python code with

>>> (42).bit_length()
6
93, but that’s an easy way to compromise the security of your program, so don’t do it

Memanggil

>>> (42).bit_length()
6
_94 dengan dua argumen akan bekerja lebih baik dalam kasus string bit yang dihasilkan secara dinamis

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
6

The first argument is a string of digits, while the second one determines the base of the numeral system. Tidak seperti literal biner, string bisa datang dari mana saja, bahkan pengguna mengetik di keyboard. For a deeper look at

>>> (42).bit_length()
6
94, you can expand the box below

Penggunaan Lain dari

>>> (42).bit_length()
6
94Tampilkan/Sembunyikan

Ada cara lain untuk memanggil

>>> (42).bit_length()
6
94. Misalnya, mengembalikan nol saat dipanggil tanpa argumen

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
7

Fitur ini menjadikannya pola umum dalam koleksi ________11______98, yang membutuhkan penyedia nilai default. Ambil ini sebagai contoh

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
8

Di sini,

>>> (42).bit_length()
6
_94 membantu menghitung kata dalam sebuah kalimat. Itu dipanggil secara otomatis setiap kali
>>> (42).bit_length()
6
_98 perlu menginisialisasi nilai kunci yang hilang dalam kamus

Penggunaan populer lainnya dari

>>> (42).bit_length()
6
_94 adalah typecasting. Misalnya, saat Anda memberikan
>>> (42).bit_length()
6
_94 nilai floating-point, nilai tersebut akan dipotong dengan menghapus komponen pecahan

>>>

if age >= 18 and not is_self_excluded:
    print("You can gamble")
9

Saat Anda memberinya string, ia mencoba mengurai angka darinya

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
0

Secara umum,

>>> (42).bit_length()
6
_94 akan menerima objek dari jenis apa pun asalkan itu mendefinisikan metode khusus yang dapat menangani konversi

Sejauh ini bagus. Tapi bagaimana dengan angka negatif?

Meniru Bit Tanda

Ketika Anda memanggil

>>> (42).bit_length()
6
86 pada bilangan bulat negatif, itu hanya menambahkan tanda minus ke string bit yang diperoleh dari nilai positif yang sesuai

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
1

Mengubah tanda angka tidak memengaruhi string bit yang mendasarinya di Python. Sebaliknya, Anda diizinkan untuk mengawali string bit dengan tanda minus saat mengubahnya menjadi bentuk desimal

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
2

Itu masuk akal di Python karena, secara internal, itu tidak menggunakan bit tanda. Anda dapat menganggap tanda bilangan bulat dengan Python sebagai informasi yang disimpan secara terpisah dari modulus

Namun, ada beberapa solusi yang memungkinkan Anda meniru urutan bit dengan panjang tetap yang berisi bit tanda

  • Bitmask
  • Operasi Modulo (
    >>> (42).bit_length()
    6
    
    _39)
  • >>> (42).bit_length()
    6
    
    _58 modul
  • >>> len("€uro".encode("utf-8"))
    6
    
    _07 modul
  • >>> len("€uro".encode("utf-8"))
    6
    
    _08 modul

Anda tahu dari bagian sebelumnya bahwa untuk memastikan panjang bit tertentu dari suatu angka, Anda dapat menggunakan bitmask yang bagus. Misalnya, untuk menyimpan satu byte, Anda dapat menggunakan topeng yang terdiri dari tepat delapan bit yang dihidupkan

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
3

Masking memaksa Python untuk sementara mengubah representasi angka dari magnitudo tanda menjadi komplemen dua, lalu kembali lagi. Jika Anda lupa tentang nilai desimal dari literal biner yang dihasilkan, yaitu sama dengan 21410, maka itu akan mewakili -4210 dalam komplemen dua. Bit paling kiri akan menjadi bit tanda

Alternatifnya, Anda dapat memanfaatkan operasi modulo yang Anda gunakan sebelumnya untuk mensimulasikan pergeseran kanan logis di Python

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
4

Jika itu terlihat terlalu berbelit-belit untuk selera Anda, maka Anda dapat menggunakan salah satu modul dari pustaka standar yang menyatakan maksud yang sama dengan lebih jelas. Misalnya, menggunakan

>>> (42).bit_length()
6
_58 akan memiliki efek yang sama

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
5

Anda pernah melihatnya sebelumnya, tetapi hanya sebagai pengingat, itu akan membonceng tipe integer yang tidak ditandatangani dari C

Modul standar lain yang dapat Anda gunakan untuk konversi semacam ini dengan Python adalah modul

>>> len("€uro".encode("utf-8"))
6
07. Ini mendefinisikan struktur data yang mirip dengan
>>> len("€uro".encode("utf-8"))
6
11 tetapi hanya diperbolehkan untuk menampung elemen dengan tipe numerik yang sama. Saat mendeklarasikan array, Anda perlu menunjukkan tipenya di depan dengan huruf yang sesuai

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
6

Misalnya,

>>> len("€uro".encode("utf-8"))
6
_12 berarti byte bertanda 8-bit, sedangkan
>>> len("€uro".encode("utf-8"))
6
13 berarti padanannya yang tidak bertanda. Ada beberapa tipe standar lainnya, seperti bilangan bulat 16-bit yang ditandatangani atau angka floating-point 32-bit

Menyalin byte mentah di antara dua larik ini mengubah cara bit diinterpretasikan. Namun, dibutuhkan dua kali jumlah memori, yang cukup boros. Untuk melakukan sedikit penulisan ulang di tempat, Anda dapat mengandalkan modul

>>> len("€uro".encode("utf-8"))
6
08 , yang menggunakan set serupa untuk deklarasi tipe

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
7

Pengepakan memungkinkan Anda meletakkan objek di memori sesuai dengan penentu tipe data C yang diberikan. Ini mengembalikan objek hanya-baca, yang berisi byte mentah dari blok memori yang dihasilkan. Nanti, Anda dapat membaca kembali byte tersebut menggunakan kumpulan kode jenis yang berbeda untuk mengubah cara mereka diterjemahkan ke dalam objek Python

Sampai saat ini, Anda telah menggunakan teknik yang berbeda untuk mendapatkan string bilangan bulat dengan panjang tetap yang diekspresikan dalam representasi komplemen dua. Jika Anda ingin mengonversi jenis urutan bit ini kembali ke bilangan bulat Python, maka Anda dapat mencoba fungsi ini

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
_8

Fungsi menerima string yang terdiri dari digit biner. Pertama, ini mengubah digit menjadi bilangan bulat unsigned, mengabaikan bit tanda. Selanjutnya, ia menggunakan dua bitmask untuk mengekstrak bit tanda dan magnitudo, yang lokasinya bergantung pada panjang bit yang ditentukan. Akhirnya, menggabungkan mereka menggunakan aritmatika biasa, mengetahui bahwa nilai yang terkait dengan bit tanda adalah negatif

Anda dapat mencobanya dengan string bit lama tepercaya dari contoh sebelumnya

>>>

if age >= 18 & ~is_self_excluded:
    print("You can gamble")
9

>>> (42).bit_length()
6
_94 Python memperlakukan semua bit sebagai besarnya, jadi tidak ada kejutan di sana. Namun, fungsi baru ini mengasumsikan string panjang 32-bit secara default, yang berarti bit tanda secara implisit sama dengan nol untuk string yang lebih pendek. Saat Anda meminta panjang bit yang cocok dengan string bit Anda, maka Anda akan mendapatkan hasil yang diharapkan

Meskipun bilangan bulat adalah tipe data yang paling tepat untuk bekerja dengan operator bitwise dalam banyak kasus, terkadang Anda perlu mengekstraksi dan memanipulasi fragmen data biner terstruktur, seperti piksel gambar. Modul

>>> len("€uro".encode("utf-8"))
6
_07 dan
>>> len("€uro".encode("utf-8"))
6
08 secara singkat menyentuh topik ini, jadi Anda akan menjelajahinya lebih detail selanjutnya

Melihat Data dalam Biner

Anda tahu cara membaca dan menafsirkan byte individual. Namun, data dunia nyata seringkali terdiri dari lebih dari satu byte untuk menyampaikan informasi. Ambil tipe data

>>> (42).bit_length()
6
_68 sebagai contoh. Satu angka floating-point dalam Python menempati sebanyak delapan byte dalam memori

Bagaimana Anda melihat byte itu?

Anda tidak bisa begitu saja menggunakan operator bitwise karena tidak bekerja dengan bilangan floating-point

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
0

Anda harus melupakan jenis data tertentu yang Anda hadapi dan memikirkannya dalam bentuk aliran byte umum. Dengan begitu, tidak masalah apa yang diwakili oleh byte di luar konteks mereka diproses oleh operator bitwise

Untuk mendapatkan

>>> len("€uro".encode("utf-8"))
6
15 dari angka floating-point dengan Python, Anda dapat mengemasnya menggunakan modul
>>> len("€uro".encode("utf-8"))
6
08 yang sudah dikenal

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
1

Abaikan karakter format yang melewati argumen pertama. Mereka tidak akan masuk akal sampai Anda masuk ke bagian di bawah ini. Di balik representasi tekstual yang agak kabur ini menyembunyikan daftar delapan bilangan bulat

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
2

Nilainya sesuai dengan byte berikutnya yang digunakan untuk mewakili angka titik-mengambang dalam biner. Anda dapat menggabungkannya untuk menghasilkan string bit yang sangat panjang

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
3

64 bit ini adalah tanda, eksponen, dan mantissa dengan presisi ganda yang Anda baca sebelumnya. Untuk mensintesis

>>> (42).bit_length()
6
_68 dari string bit yang serupa, Anda dapat membalik prosesnya

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
4

>>> len("€uro".encode("utf-8"))
6
_23 mengembalikan tuple karena memungkinkan Anda membaca lebih dari satu nilai sekaligus. Misalnya, Anda dapat membaca string bit yang sama dengan empat bilangan bulat bertanda 16-bit

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
5

Seperti yang Anda lihat, cara interpretasi bit string harus diketahui sebelumnya untuk menghindari berakhir dengan data yang kacau. Satu pertanyaan penting yang perlu Anda tanyakan pada diri sendiri adalah dari mana akhir aliran byte Anda harus mulai membaca—kiri atau kanan. Baca terus untuk mencari tahu

Urutan Byte

Tidak ada perselisihan tentang urutan bit dalam satu byte. Anda akan selalu menemukan bit paling tidak signifikan pada indeks nol dan bit paling signifikan pada indeks tujuh, terlepas dari bagaimana mereka ditata secara fisik dalam memori. Operator pergeseran bitwise mengandalkan konsistensi ini

Namun, tidak ada konsensus untuk urutan byte dalam potongan data multibyte. Sepotong informasi yang terdiri lebih dari satu byte dapat dibaca dari kiri ke kanan seperti teks bahasa Inggris atau dari kanan ke kiri seperti bahasa Arab, misalnya. Komputer melihat byte dalam aliran biner seperti manusia melihat kata-kata dalam sebuah kalimat

Tidak masalah dari arah mana komputer memilih untuk membaca byte selama mereka menerapkan aturan yang sama di mana-mana. Sayangnya, arsitektur komputer yang berbeda menggunakan pendekatan yang berbeda, yang membuat transfer data di antara mereka menjadi sulit

Big-Endian vs Little-Endian

Mari kita ambil bilangan bulat 32-bit unsigned yang sesuai dengan angka 196910, yang merupakan tahun ketika Monty Python pertama kali muncul di TV. Dengan semua nol di depannya, ia memiliki representasi biner berikut 000000000000000000000111101100012

Bagaimana Anda menyimpan nilai seperti itu di memori komputer?

Jika Anda membayangkan memori sebagai pita satu dimensi yang terdiri dari byte, maka Anda perlu memecah data tersebut menjadi byte individual dan mengaturnya dalam blok yang berdekatan. Beberapa merasa wajar untuk memulai dari ujung kiri karena begitulah cara mereka membaca, sementara yang lain lebih suka memulai dari ujung kanan

Urutan Byte Alamat N Alamat N+1 Alamat N+2 Alamat N+3 Big-Endian000000002000000002000001112101100012 Little-Endian101100012000001112000000002000000002

Ketika byte ditempatkan dari kiri ke kanan, byte yang paling signifikan ditugaskan ke alamat memori terendah. Ini dikenal sebagai tatanan big-endian. Sebaliknya, ketika byte disimpan dari kanan ke kiri, byte yang paling tidak signifikan didahulukan. Itu disebut pesanan little-endian

Catatan. Nama-nama lucu ini terinspirasi dari novel Gulliver's Travels abad ke-18 karya Jonathan Swift. Penulis menggambarkan konflik antara Little-Endians dan Big-Endians mengenai cara yang benar untuk memecahkan cangkang telur rebus. Sementara Little-Endian lebih suka memulai dengan ujung kecil yang runcing, Big-Endian lebih menyukai ujung yang besar

Cara mana yang lebih baik?

Dari sudut pandang praktis, tidak ada keuntungan nyata menggunakan salah satunya. Mungkin ada beberapa keuntungan kecil dalam kinerja di tingkat perangkat keras, tetapi Anda tidak akan menyadarinya. Protokol jaringan utama menggunakan urutan big-endian, yang memungkinkan mereka memfilter paket data lebih cepat mengingat desain hierarki pengalamatan IP. Selain itu, beberapa orang mungkin merasa lebih nyaman bekerja dengan urutan byte tertentu saat melakukan debug

Either way, jika Anda tidak melakukannya dengan benar dan mencampuradukkan kedua standar, maka hal buruk mulai terjadi

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
6

Saat Anda membuat serial beberapa nilai ke aliran byte menggunakan satu konvensi dan mencoba membacanya kembali dengan yang lain, Anda akan mendapatkan hasil yang sama sekali tidak berguna. Skenario ini kemungkinan besar terjadi saat data dikirim melalui jaringan, tetapi Anda juga dapat mengalaminya saat membaca file lokal dalam format tertentu. Misalnya, header bitmap Windows selalu menggunakan little-endian, sedangkan JPEG dapat menggunakan kedua urutan byte tersebut

Endianness Asli

Untuk mengetahui endianness platform Anda, Anda dapat menggunakan modul

>>> len("€uro".encode("utf-8"))
6
24

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
7

Anda tidak dapat mengubah endianness, karena ini adalah fitur intrinsik dari arsitektur CPU Anda. Tidak mungkin untuk mengejeknya untuk tujuan pengujian tanpa virtualisasi perangkat keras seperti QEMU, jadi bahkan VirtualBox yang populer pun tidak akan membantu

Khususnya, keluarga prosesor x86 dari Intel dan AMD, yang menggerakkan sebagian besar laptop dan desktop modern, adalah produk kecil. Perangkat seluler didasarkan pada arsitektur ARM berenergi rendah, sementara beberapa arsitektur lama seperti Motorola 68000 kuno hanya merupakan arsitektur big-endian

Untuk informasi tentang menentukan endianness dalam C, perluas kotak di bawah ini

Memeriksa Urutan Byte di CTampilkan/Sembunyikan

Secara historis, cara untuk mendapatkan endianness mesin Anda di C adalah dengan mendeklarasikan bilangan bulat kecil dan kemudian membaca byte pertamanya dengan sebuah pointer

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
8

Jika nilainya keluar lebih tinggi dari nol, maka byte yang disimpan di alamat memori terendah harus menjadi yang paling tidak signifikan

Setelah Anda mengetahui endianness asli mesin Anda, Anda ingin mengonversi antara urutan byte yang berbeda saat memanipulasi data biner. Cara universal untuk melakukannya, terlepas dari tipe data yang ada, adalah membalikkan objek

>>> len("€uro".encode("utf-8"))
6
15 generik atau urutan bilangan bulat yang mewakili byte tersebut

>>>

>>> age = 18
>>> is_self_excluded = True
>>> age >= 18 & ~is_self_excluded  # Bitwise logical operators
True
>>> age >= 18 and not is_self_excluded  # Logical operators
False
9

Namun, seringkali lebih nyaman menggunakan modul

>>> len("€uro".encode("utf-8"))
6
08, yang memungkinkan Anda menentukan tipe data C standar. Selain itu, ini memungkinkan Anda untuk meminta urutan byte yang diberikan dengan pengubah opsional

>>>

>>> age >= (18 & ~is_self_excluded)
True
0

Tanda lebih besar dari (

>>> len("€uro".encode("utf-8"))
6
_27) menunjukkan bahwa byte ditata dalam urutan big-endian, sedangkan simbol kurang dari (
>>> len("€uro".encode("utf-8"))
6
28) sesuai dengan little-endian. Jika Anda tidak menentukannya, maka native endianness diasumsikan. Ada beberapa pengubah lagi, seperti tanda seru (
>>> len("€uro".encode("utf-8"))
6
29), yang menandakan urutan byte jaringan

Urutan Byte Jaringan

Jaringan komputer terbuat dari perangkat yang heterogen seperti laptop, desktop, tablet, smartphone, dan bahkan bola lampu yang dilengkapi dengan adaptor Wi-Fi. Mereka semua membutuhkan protokol dan standar yang disepakati, termasuk urutan byte untuk transmisi biner, untuk berkomunikasi secara efektif

Di awal Internet, diputuskan bahwa urutan byte untuk protokol jaringan tersebut akan menjadi big-endian

Program yang ingin berkomunikasi melalui jaringan dapat mengambil API C klasik, yang mengabstraksi detail seluk beluk dengan lapisan soket. Python membungkus API itu melalui modul

>>> len("€uro".encode("utf-8"))
6
30 bawaan. Namun, kecuali Anda menulis protokol biner khusus, Anda mungkin ingin memanfaatkan abstraksi tingkat yang lebih tinggi, seperti protokol HTTP, yang berbasis teks

Di mana modul

>>> len("€uro".encode("utf-8"))
6
_30 dapat berguna adalah dalam konversi urutan byte. Itu memperlihatkan beberapa fungsi dari C API, dengan nama mereka yang khas dan membingungkan

>>>

>>> age >= (18 & ~is_self_excluded)
True
1

Jika host Anda sudah menggunakan urutan byte big-endian, maka tidak ada yang perlu dilakukan. Nilainya akan tetap sama

Bitmask

Bitmask berfungsi seperti stensil grafiti yang menghalangi cat agar tidak disemprotkan ke area permukaan tertentu. Ini memungkinkan Anda mengisolasi bit untuk menerapkan beberapa fungsi padanya secara selektif. Bitmasking melibatkan operator logis bitwise dan operator shift bitwise yang telah Anda baca

Anda dapat menemukan bitmask dalam banyak konteks berbeda. Misalnya, subnet mask dalam pengalamatan IP sebenarnya adalah bitmask yang membantu Anda mengekstrak alamat jaringan. Saluran piksel, yang sesuai dengan warna merah, hijau, dan biru dalam model RGB, dapat diakses dengan bitmask. Anda juga dapat menggunakan bitmask untuk menentukan bendera Boolean yang kemudian dapat Anda kemas di bidang bit

Ada beberapa jenis operasi umum yang terkait dengan bitmask. Anda akan melihat sekilas beberapa di antaranya di bawah ini

Mendapatkan Sedikit

Untuk membaca nilai bit tertentu pada posisi tertentu, Anda dapat menggunakan bitwise AND terhadap bitmask yang hanya terdiri dari satu bit pada indeks yang diinginkan.

>>>

>>> age >= (18 & ~is_self_excluded)
True
2

Topeng akan menekan semua bit kecuali yang Anda minati. Ini akan menghasilkan nol atau pangkat dua dengan eksponen yang sama dengan indeks bit. Jika Anda ingin mendapatkan jawaban ya-atau-tidak yang sederhana, maka Anda dapat menggeser ke kanan dan mencentang bit yang paling tidak signifikan

>>>

>>> age >= (18 & ~is_self_excluded)
True
3

Kali ini, ini akan menormalkan nilai bit sehingga tidak pernah melebihi satu. Anda kemudian dapat menggunakan fungsi itu untuk mendapatkan nilai Boolean

>>> (42).bit_length()
6
28 atau
>>> (42).bit_length()
6
29 daripada nilai numerik

Mengatur Sedikit

Mengatur sedikit mirip dengan mendapatkan satu. Anda memanfaatkan bitmask yang sama seperti sebelumnya, tetapi alih-alih menggunakan bitwise AND, Anda menggunakan operator bitwise OR

>>>

>>> age >= (18 & ~is_self_excluded)
True
4

Topeng mempertahankan semua bit asli sambil menerapkan bit biner pada indeks yang ditentukan. Seandainya bit itu sudah disetel, nilainya tidak akan berubah

Menghapus Sedikit

Untuk menghapus sedikit, Anda ingin menyalin semua digit biner sambil menerapkan nol pada satu indeks tertentu. Anda dapat mencapai efek ini dengan menggunakan bitmask yang sama sekali lagi, tetapi dalam bentuk terbalik

>>>

>>> age >= (18 & ~is_self_excluded)
True
5

Menggunakan bitwise NOT pada angka positif selalu menghasilkan nilai negatif di Python. Meskipun ini umumnya tidak diinginkan, tidak masalah di sini karena Anda segera menerapkan operator AND bitwise. Ini, pada gilirannya, memicu konversi topeng menjadi representasi komplemen dua, yang memberi Anda hasil yang diharapkan

Beralih Sedikit

Terkadang berguna untuk dapat mengaktifkan dan menonaktifkan sedikit lagi secara berkala. Itu adalah peluang sempurna untuk operator XOR bitwise, yang dapat membalikkan bit Anda seperti itu

>>>

>>> age >= (18 & ~is_self_excluded)
True
6

Perhatikan bitmask yang sama digunakan lagi. Biner satu pada posisi yang ditentukan akan membuat bit pada indeks itu membalikkan nilainya. Memiliki nol biner di tempat yang tersisa akan memastikan bahwa sisa bit akan disalin

Kelebihan Operator Bitwise

Domain utama operator bitwise adalah bilangan bulat. Di situlah mereka paling masuk akal. Namun, Anda juga pernah melihatnya digunakan dalam konteks Boolean, di mana mereka menggantikan operator logika. Python menyediakan implementasi alternatif untuk beberapa operatornya dan memungkinkan Anda membebani mereka untuk tipe data baru

Meskipun proposal untuk membebani operator logis dengan Python ditolak, Anda dapat memberikan arti baru ke salah satu operator bitwise. Banyak perpustakaan populer, dan bahkan perpustakaan standar, memanfaatkannya

Tipe Data Bawaan

Operator bitwise Python ditentukan untuk tipe data bawaan berikut

  • >>> (42).bit_length()
    6
    
    _73
  • >>> len("€uro".encode("utf-8"))
    6
    
    _35
  • >>> len("€uro".encode("utf-8"))
    6
    
    _36 dan
  • >>> len("€uro".encode("utf-8"))
    6
    
    _38 (sejak Python 3. 9)

Ini bukan fakta yang diketahui secara luas, tetapi operator bitwise dapat melakukan operasi dari aljabar himpunan, seperti penyatuan, perpotongan, dan perbedaan simetris, serta menggabungkan dan memperbarui kamus

Catatan. Pada saat penulisan, Python 3. 9 belum dirilis, tetapi Anda dapat mengintip fitur bahasa yang akan datang menggunakan Docker atau pyenv

Ketika

>>> (42).bit_length()
6
_31 dan
>>> (42).bit_length()
6
32 adalah set Python, maka operator bitwise sesuai dengan metode berikut

Set MethodBitwise Operator

>>> len("€uro".encode("utf-8"))
6
41
>>> 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
>>> len("€uro".encode("utf-8"))
6
43
>>> (42).bit_length()
6
09
>>> len("€uro".encode("utf-8"))
6
45
>>> 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
>>> len("€uro".encode("utf-8"))
6
47
>>> (42).bit_length()
6
06
>>> len("€uro".encode("utf-8"))
6
49
>>> 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
>>> len("€uro".encode("utf-8"))
6
51
>>> (42).bit_length()
6
12

Mereka melakukan hal yang hampir sama, jadi terserah Anda sintaks mana yang akan digunakan. Selain itu, ada juga operator minus kelebihan beban (

>>> (42).bit_length()
6
64), yang menerapkan perbedaan dua set. Untuk melihatnya beraksi, asumsikan Anda memiliki dua set buah dan sayuran berikut

>>>

>>> age >= (18 & ~is_self_excluded)
True
7

Mereka berbagi satu anggota yang sama, yang sulit untuk diklasifikasikan, tetapi elemen lainnya terpisah

Satu hal yang harus diperhatikan adalah _

>>> len("€uro".encode("utf-8"))
6
54 yang tidak dapat diubah, yang tidak memiliki metode untuk pembaruan di tempat. Namun, ketika Anda menggunakan rekan operator bitwise mereka, artinya sedikit berbeda

>>>

>>> age >= (18 & ~is_self_excluded)
True
8

Sepertinya

>>> len("€uro".encode("utf-8"))
6
54 tidak begitu abadi ketika Anda menggunakan operator bitwise, tetapi masalahnya ada dalam detailnya. Inilah yang sebenarnya terjadi

>>> age >= (18 & ~is_self_excluded)
True
_9

Alasan ini berfungsi untuk kedua kalinya adalah karena Anda tidak mengubah objek asli yang tidak dapat diubah. Sebagai gantinya, Anda membuat yang baru dan menugaskannya ke variabel yang sama lagi

Python

>>> len("€uro".encode("utf-8"))
6
_38 hanya mendukung bitwise OR, yang berfungsi seperti operator gabungan. Anda dapat menggunakannya untuk memperbarui kamus di tempat atau menggabungkan dua kamus menjadi yang baru

>>>

>>> (age >= 18) & ~is_self_excluded
0
0

Versi tambahan dari operator bitwise setara dengan

>>> len("€uro".encode("utf-8"))
6
57

Modul Pihak Ketiga

Banyak pustaka populer, termasuk NumPy, panda, dan SQLAlchemy, membebani operator bitwise untuk tipe data spesifiknya. Ini adalah tempat yang paling mungkin Anda akan menemukan operator bitwise di Python karena mereka tidak lagi sering digunakan dalam arti aslinya.

Misalnya, NumPy menerapkannya ke data vektor dengan cara yang tepat

>>>

>>> (age >= 18) & ~is_self_excluded
0
1

Dengan cara ini, Anda tidak perlu menerapkan operator bitwise yang sama secara manual ke setiap elemen array. Tetapi Anda tidak dapat melakukan hal yang sama dengan daftar biasa di Python

panda menggunakan NumPy di ​​belakang layar, dan juga menyediakan versi beban berlebih dari operator bitwise untuk objek

>>> len("€uro".encode("utf-8"))
6
58 dan
>>> len("€uro".encode("utf-8"))
6
59. Namun, mereka berperilaku seperti yang Anda harapkan. Satu-satunya perbedaan adalah bahwa mereka melakukan pekerjaan biasa pada vektor dan matriks angka, bukan pada skalar individual

Hal-hal menjadi lebih menarik dengan perpustakaan yang memberikan operator bitwise arti yang sama sekali baru. Misalnya, SQLAlchemy menyediakan sintaks ringkas untuk menanyakan database

>>> (age >= 18) & ~is_self_excluded
0
_2

Operator bitwise 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
_1) pada akhirnya akan menerjemahkan ke bagian kueri SQL. Namun, itu tidak terlalu jelas, setidaknya tidak untuk IDE saya, yang mengeluh tentang penggunaan operator bitwise yang tidak sehat ketika melihat mereka dalam jenis ekspresi ini. Segera disarankan untuk mengganti setiap kemunculan
>>> 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 dengan logika
>>> (42).bit_length()
6
25, tanpa mengetahui bahwa hal itu akan membuat kode berhenti bekerja

Jenis kelebihan operator ini adalah praktik kontroversial yang mengandalkan sihir implisit yang harus Anda ketahui sebelumnya. Beberapa bahasa pemrograman seperti Java mencegah penyalahgunaan seperti itu dengan melarang sama sekali kelebihan beban operator. Python lebih liberal dalam hal itu dan percaya bahwa Anda tahu apa yang Anda lakukan

Jenis Data Kustom

Untuk menyesuaikan perilaku operator bitwise Python, Anda harus mendefinisikan sebuah kelas dan kemudian mengimplementasikan yang sesuai di dalamnya. Pada saat yang sama, Anda tidak dapat mendefinisikan ulang perilaku operator bitwise untuk jenis yang sudah ada. Kelebihan beban operator hanya mungkin terjadi pada tipe data baru

Berikut adalah ikhtisar singkat tentang metode khusus yang memungkinkan Anda membebani operator bitwise

Magic MethodExpression

>>> len("€uro".encode("utf-8"))
6
63
>>> len("€uro".encode("utf-8"))
6
64
>>> len("€uro".encode("utf-8"))
6
65
>>> len("€uro".encode("utf-8"))
6
66
>>> len("€uro".encode("utf-8"))
6
67
>>> len("€uro".encode("utf-8"))
6
68
>>> len("€uro".encode("utf-8"))
6
69
>>> len("€uro".encode("utf-8"))
6
70
>>> len("€uro".encode("utf-8"))
6
71
>>> len("€uro".encode("utf-8"))
6
72
>>> len("€uro".encode("utf-8"))
6
73
>>> len("€uro".encode("utf-8"))
6
74
>>> len("€uro".encode("utf-8"))
6
75
>>> len("€uro".encode("utf-8"))
6
76
>>> len("€uro".encode("utf-8"))
6
77
>>> len("€uro".encode("utf-8"))
6
78
>>> len("€uro".encode("utf-8"))
6
79
>>> len("€uro".encode("utf-8"))
6
80
>>> len("€uro".encode("utf-8"))
6
81
>>> len("€uro".encode("utf-8"))
6
82
>>> len("€uro".encode("utf-8"))
6
83
>>> len("€uro".encode("utf-8"))
6
84
>>> len("€uro".encode("utf-8"))
6
85
>>> len("€uro".encode("utf-8"))
6
86
>>> len("€uro".encode("utf-8"))
6
87
>>> len("€uro".encode("utf-8"))
6
88
>>> len("€uro".encode("utf-8"))
6
89
>>> len("€uro".encode("utf-8"))
6
90
>>> len("€uro".encode("utf-8"))
6
91
>>> len("€uro".encode("utf-8"))
6
92
>>> len("€uro".encode("utf-8"))
6
93
>>> len("€uro".encode("utf-8"))
6
94

Anda tidak perlu mendefinisikan semuanya. Misalnya, untuk memiliki sintaks yang sedikit lebih nyaman untuk menambahkan dan menambahkan elemen ke a , cukup menerapkan hanya

>>> len("€uro".encode("utf-8"))
6
95 dan
>>> len("€uro".encode("utf-8"))
6
96

>>>

>>> (age >= 18) & ~is_self_excluded
0
3

Kelas yang ditentukan pengguna ini membungkus deque untuk menggunakan kembali implementasinya dan menambahnya dengan dua metode tambahan yang memungkinkan untuk menambahkan item ke ujung kiri atau kanan koleksi

Steganografi Bit Paling Tidak Signifikan

Wah, itu banyak yang harus diproses. Jika Anda masih bingung, bertanya-tanya mengapa Anda ingin menggunakan operator bitwise, maka jangan khawatir. Saatnya menunjukkan apa yang dapat Anda lakukan dengan mereka dengan cara yang menyenangkan

Untuk mengikuti contoh di bagian ini, Anda dapat mengunduh kode sumber dengan mengklik tautan di bawah ini

Get the Source Code. Click here to get the source code you’ll use to learn about Python’s bitwise operators in this tutorial

Anda akan belajar tentang steganografi dan menerapkan konsep ini untuk menyematkan file arbitrer secara diam-diam dalam gambar bitmap

Kriptografi vs Steganografi

Kriptografi adalah tentang mengubah pesan menjadi pesan yang hanya dapat dibaca oleh mereka yang memiliki kunci yang tepat. Semua orang masih dapat melihat pesan terenkripsi, tetapi itu tidak masuk akal bagi mereka. Salah satu bentuk kriptografi pertama adalah cipher substitusi, seperti yang dinamai Julius Caesar

Steganografi mirip dengan kriptografi karena juga memungkinkan Anda berbagi pesan rahasia dengan audiens yang Anda inginkan. Namun, alih-alih menggunakan enkripsi, ia dengan cerdik menyembunyikan informasi di media yang tidak menarik perhatian. Contohnya termasuk menggunakan tinta tak terlihat atau menulis akrostik di mana huruf pertama dari setiap kata atau baris membentuk pesan rahasia

Kecuali Anda tahu bahwa pesan rahasia disembunyikan dan metode untuk memulihkannya, Anda mungkin akan mengabaikan operatornya. Anda dapat menggabungkan kedua teknik agar lebih aman, menyembunyikan pesan terenkripsi daripada yang asli

Ada banyak cara untuk menyelundupkan data rahasia di dunia digital. Secara khusus, format file yang membawa banyak data, seperti file audio, video, atau gambar, sangat cocok karena memberi Anda banyak ruang untuk bekerja. Perusahaan yang merilis materi berhak cipta mungkin menggunakan steganografi untuk menandai salinan individual dan melacak sumber kebocoran, misalnya

Di bawah, Anda akan menyuntikkan data rahasia ke bitmap biasa, yang mudah dibaca dan ditulis dengan Python tanpa memerlukan ketergantungan eksternal

Berformat File Bitmap

Kata bitmap biasanya mengacu pada format file Windows bitmap (

>>> len("€uro".encode("utf-8"))
6
97), yang mendukung beberapa cara alternatif untuk merepresentasikan piksel. Untuk membuat hidup lebih mudah, Anda akan berasumsi bahwa piksel disimpan dalam format RGB (merah, hijau, dan biru) 24-bit yang tidak terkompresi. Piksel akan memiliki tiga saluran warna yang masing-masing dapat menyimpan nilai dari 010 hingga 25510

Setiap bitmap dimulai dengan header file, yang berisi metadata seperti lebar dan tinggi gambar. Berikut adalah beberapa bidang yang menarik dan posisinya relatif terhadap awal tajuk

FieldByte OffsetBytes LengthTypeSample ValueSignature

>>> len("€uro".encode("utf-8"))
6
982StringBMFile Size
>>> len("€uro".encode("utf-8"))
6
994Unsigned int7,629,186Reserved #1
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
002Bytes0Reserved #2
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
012Bytes0Pixels Offset
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
024Unsigned int122Pixels Size
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
034Unsigned int7,629,064Image Width
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
044Unsigned int1,954Image Height
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
054Unsigned int1,301Bits Per Pixel
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
062Unsigned short24Compression
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
074Unsigned int0Colors Palette
>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
084Unsigned int0

Anda dapat menyimpulkan dari header ini bahwa bitmap yang sesuai memiliki lebar 1.954 piksel dan tinggi 1.301 piksel. Itu tidak menggunakan kompresi, juga tidak memiliki palet warna. Setiap piksel menempati 24 bit, atau 3 byte, dan data piksel mentah dimulai pada offset 12210

Anda dapat membuka bitmap dalam mode biner, mencari offset yang diinginkan, membaca jumlah byte yang diberikan, dan membatalkan serialisasi menggunakan

>>> len("€uro".encode("utf-8"))
6
08 seperti sebelumnya

>>> (age >= 18) & ~is_self_excluded
0
_4

Perhatikan bahwa semua bidang bilangan bulat dalam bitmap disimpan dalam urutan byte little-endian

Anda mungkin telah melihat perbedaan kecil antara jumlah byte piksel yang dinyatakan di header dan yang akan dihasilkan dari ukuran gambar. Saat Anda mengalikan 1.954 piksel × 1.301 piksel × 3 byte, Anda mendapatkan nilai 2.602 byte kurang dari 7.629.064

Ini karena byte piksel diisi dengan nol sehingga setiap baris merupakan kelipatan empat byte. Jika lebar gambar dikalikan tiga byte merupakan kelipatan empat, maka padding tidak diperlukan. Jika tidak, byte kosong ditambahkan di akhir setiap baris

Catatan. Untuk menghindari timbulnya kecurigaan, Anda harus mempertimbangkan bantalan itu dengan melewatkan byte kosong. Kalau tidak, itu akan menjadi hadiah yang jelas bagi seseorang yang tahu apa yang harus dicari

Bitmap menyimpan baris piksel secara terbalik, mulai dari bawah, bukan dari atas. Juga, setiap piksel diserialisasi ke vektor saluran warna dalam urutan BGR yang agak aneh daripada RGB. Namun, ini tidak relevan dengan tugas menyembunyikan data rahasia

Sembunyikan dan Cari Bitwise

Anda dapat menggunakan operator bitwise untuk menyebarkan data khusus melalui byte piksel berurutan. Idenya adalah untuk menimpa bit yang paling tidak signifikan di masing-masingnya dengan bit yang berasal dari byte rahasia berikutnya. Ini akan menghasilkan paling sedikit noise, tetapi Anda dapat bereksperimen dengan menambahkan lebih banyak bit untuk mencapai keseimbangan antara ukuran data yang disuntikkan dan distorsi piksel

Catatan. Menggunakan steganografi bit paling tidak signifikan tidak memengaruhi ukuran file dari bitmap yang dihasilkan. Itu akan tetap sama dengan file aslinya

Dalam beberapa kasus, bit yang sesuai akan sama, sehingga tidak ada perubahan nilai piksel apa pun. Namun, bahkan dalam skenario terburuk, warna piksel hanya akan berbeda sepersekian persen. Anomali sekecil itu akan tetap tidak terlihat oleh mata manusia tetapi dapat dideteksi dengan steganalisis, yang menggunakan statistik

Lihatlah gambar-gambar yang dipotong ini

Apa biner di python?

Yang di sebelah kiri berasal dari bitmap asli, sedangkan gambar di sebelah kanan menggambarkan bitmap yang diproses dengan video tersemat yang disimpan pada bit yang paling tidak signifikan. Bisakah Anda melihat perbedaannya?

Sepotong kode berikut menyandikan data rahasia ke bitmap

>>> (age >= 18) & ~is_self_excluded
0
5

Untuk setiap byte data rahasia dan delapan byte data piksel yang sesuai, tidak termasuk byte pad, ia menyiapkan daftar bit untuk disebarkan. Selanjutnya, itu menimpa bit paling tidak signifikan di masing-masing dari delapan byte menggunakan bitmask yang relevan. Hasilnya diubah menjadi objek

>>> len("€uro".encode("utf-8"))
6
_15 dan ditetapkan kembali ke bagian bitmap asalnya

Untuk mendekode file dari bitmap yang sama, Anda perlu mengetahui berapa banyak byte rahasia yang ditulis padanya. Anda dapat mengalokasikan beberapa byte di awal aliran data untuk menyimpan nomor ini, atau Anda dapat menggunakan bidang yang dicadangkan dari header bitmap

>>> (age >= 18) & ~is_self_excluded
0
_6

Ini melompat ke offset kanan dalam file, membuat serial Python

>>> (42).bit_length()
6
73 ke byte mentah, dan menuliskannya

Anda mungkin juga ingin menyimpan nama file rahasia Anda. Karena dapat memiliki panjang yang sewenang-wenang, masuk akal untuk membuat cerita bersambung menggunakan string yang diakhiri null, yang akan mendahului konten file. Untuk membuat string seperti itu, Anda perlu menyandikan objek Python

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
12 ke byte dan secara manual menambahkan byte nol di bagian akhir

>>>

>>> (age >= 18) & ~is_self_excluded
0
7

Selain itu, tidak ada salahnya membuang direktori induk redundan dari jalur menggunakan

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
13

Kode sampel yang melengkapi artikel ini akan memungkinkan Anda menyandikan, mendekode, dan menghapus file rahasia dari bitmap yang diberikan dengan perintah berikut

>>> (age >= 18) & ~is_self_excluded
0
_8

Ini adalah modul yang dapat dijalankan yang dapat dijalankan dengan memanggil direktori yang melingkupinya. Anda juga dapat membuat arsip format ZIP portabel dari isinya untuk memanfaatkan dukungan aplikasi Python ZIP

Program ini bergantung pada modul dari pustaka standar yang disebutkan dalam artikel dan beberapa lainnya yang mungkin belum pernah Anda dengar sebelumnya. Modul penting adalah

>>> for char in "€uro":
..     print(char, len(char.encode("utf-8")))
...
€ 3
u 1
r 1
o 1
14, yang memaparkan antarmuka Python ke file yang dipetakan memori. Mereka membiarkan Anda memanipulasi file besar menggunakan API file standar dan API urutan. Seolah-olah file tersebut adalah satu daftar besar yang dapat diubah yang dapat Anda potong

Silakan bermain-main dengan bitmap yang dilampirkan pada materi pendukung. Ini berisi sedikit kejutan untuk Anda

Kesimpulan

Menguasai operator bitwise Python memberi Anda kebebasan tertinggi untuk memanipulasi data biner dalam proyek Anda. Anda sekarang mengetahui sintaks dan rasa yang berbeda serta tipe data yang mendukungnya. Anda juga dapat menyesuaikan perilaku mereka untuk kebutuhan Anda sendiri

Dalam tutorial ini, Anda belajar caranya

  • Use Python bitwise operators to manipulate individual bits
  • Read and write binary data in a platform-agnostic way
  • Use bitmasks to pack information on a single byte
  • Overload Python bitwise operators in custom data types
  • Hide secret messages in digital images

Anda juga belajar bagaimana komputer menggunakan sistem biner untuk merepresentasikan berbagai jenis informasi digital. Anda melihat beberapa cara populer untuk menginterpretasikan bit dan cara mengurangi kurangnya tipe data yang tidak ditandatangani di Python serta cara unik Python untuk menyimpan bilangan bulat di memori

Dengan informasi ini, Anda siap memanfaatkan sepenuhnya data biner dalam kode Anda. Untuk mendownload source code yang digunakan pada contoh watermarking dan melanjutkan percobaan dengan operator bitwise, Anda bisa mengklik link di bawah ini

Get the Source Code. Click here to get the source code you’ll use to learn about Python’s bitwise operators in this tutorial

Tandai sebagai Selesai

Tonton Sekarang Tutorial ini memiliki kursus video terkait yang dibuat oleh tim Real Python. Tonton bersama dengan tutorial tertulis untuk memperdalam pemahaman Anda. Operator Biner, Byte, dan Bitwise dengan Python

🐍 Trik Python 💌

Dapatkan Trik Python singkat & manis yang dikirim ke kotak masuk Anda setiap beberapa hari. Tidak pernah ada spam. Berhenti berlangganan kapan saja. Dikuratori oleh tim Real Python

Apa biner di python?

Kirimi Saya Trik Python »

Tentang Bartosz Zaczyński

Apa biner di python?
Apa biner di python?

Bartosz adalah instruktur bootcamp, penulis, dan programmer poliglot yang jatuh cinta dengan Python. Dia membantu murid-muridnya masuk ke rekayasa perangkat lunak dengan berbagi lebih dari satu dekade pengalaman komersial di industri TI

» Lebih lanjut tentang Bartosz


Setiap tutorial di Real Python dibuat oleh tim pengembang sehingga memenuhi standar kualitas tinggi kami. Anggota tim yang mengerjakan tutorial ini adalah

Apa biner di python?

Aldren

Apa biner di python?

Daud

Apa biner di python?

Geir Arne

Apa biner di python?

Joanna

Apa biner di python?

Yakub

Master Keterampilan Python Dunia Nyata Dengan Akses Tanpa Batas ke Python Nyata

Bergabunglah dengan kami dan dapatkan akses ke ribuan tutorial, kursus video langsung, dan komunitas pakar Pythonista

Tingkatkan Keterampilan Python Anda »

Guru Keterampilan Python Dunia Nyata
Dengan Akses Tak Terbatas ke Real Python

Bergabunglah dengan kami dan dapatkan akses ke ribuan tutorial, kursus video langsung, dan komunitas ahli Pythonista

Tingkatkan Keterampilan Python Anda »

Bagaimana menurut anda?

Nilai artikel ini

Tweet Bagikan Bagikan Email

Apa takeaway # 1 Anda atau hal favorit yang Anda pelajari?

Kiat Berkomentar. Komentar yang paling berguna adalah yang ditulis dengan tujuan belajar dari atau membantu siswa lain. dan dapatkan jawaban atas pertanyaan umum di portal dukungan kami