From 87e4e6410361a45ace65b8128ef844fd65a821de Mon Sep 17 00:00:00 2001 From: Colin Leach Date: Fri, 8 Dec 2023 13:12:43 -0700 Subject: [PATCH 1/4] bitwise-operators concept --- concepts/bitwise-operators/.meta/config.json | 4 +- concepts/bitwise-operators/about.md | 141 ++++++++++++++++++- concepts/bitwise-operators/links.json | 16 +-- 3 files changed, 144 insertions(+), 17 deletions(-) diff --git a/concepts/bitwise-operators/.meta/config.json b/concepts/bitwise-operators/.meta/config.json index 9b9e8da5a9..7e1fc38dfe 100644 --- a/concepts/bitwise-operators/.meta/config.json +++ b/concepts/bitwise-operators/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "TODO: add blurb for this concept", - "authors": ["bethanyg", "cmccandless"], + "blurb": "Python supports bitwise operations such as left/right shift, and, or, xor.", + "authors": ["BethanyG", "colinleach"], "contributors": [] } diff --git a/concepts/bitwise-operators/about.md b/concepts/bitwise-operators/about.md index c628150d56..03e177df41 100644 --- a/concepts/bitwise-operators/about.md +++ b/concepts/bitwise-operators/about.md @@ -1,2 +1,141 @@ -#TODO: Add about for this concept. +# About +Down at the hardware level, transistors can only be on or off: two states that we traditionaly represent with `1` and `0`. +These are `binary digits`, abbreviated as `bits`. + +This is particularly important for systems pprogrammers working in low-level languages. +However, for most of the history of computing the priority has been to find increasing sophisticated ways to hide the binary reality from most users. +Hence we work with `int`, `float`, `string` and many other types, up to audio and video formats. + +Nevertheless, bitwise operations can sometimes have significant advantages in speed and memory efficiency, even in a high-level scripting language like Python. + +## Entering and displaying binary numbers + +Unsurprisingly, Python interacts with the user using decimal numbers by default, but the programmer can override this. + +Binary numbers are just entered with a `0b` prefix, just as `0x` can be used for hexadecimal (hex numbers are a concise way to represent groups of 4 bits). +Note that these are all really an `int`, just displayed differently. + +There are multiple ways to convert integers to binary strings, varying in whether they include the `0b` prefix and whether they support left-padding with zeros. + +```python +>>> 0b10111 # binary entry +23 + +>>> bin(23) # int to binary string, with prefix +'0b10111' + +>>> n = 23 +>>> format(n, '08b') # no prefix, padded to 8 digits +'00010111' +>>> f"{n} in decimal is {n:08b} in binary and {n:x} in hex" # same, but using an f-string +'23 in decimal is 00010111 in binary and 17 in hex' +``` + +## [`Shift operators`][bitwise-operators] + +The left-shift operator `x << y` simply moves all the bits in `x` by `y` places to the left, filling the new gaps with zeros. +Note that this is arithmetically identical to multiplying by `2**y`. + +The right-shift operator `x >> y` does the opposite (for non-negative numbers, see below for how negative numbers work). +This is arithmetically identical to integer division `x // 2**y`. + +```python +>>> x = 8 +>>> format(x, '08b') +'00001000' + +>>> x << 2 # left shift +32 +>>> format(x << 2, '08b') +'00100000' +>>> format(x >> 2, '08b') # right shift +'00000010' +``` + +## [`Bitwise logic`][bitwise-operators] + +In a previous concept, we saw the logical operators `and`, `or` and `not` which operate on `True` and `False` values. + +In the bitwise equivalent, the operators are applied to each bit in the number, treating `1` as `True` and `0` as `False.` +An example with bitwise `&` (and) might make this clearer: + +```python +>>> x = 0b01100110 +>>> y = 0b00101010 +>>> format(x & y, '08b') +'00100010' +``` + +Only positions with a `1` in _both_ the input strings are set to `1` in the output. + +Bitwise `&` is commonly used as a way to isolate single bits in a compacted set of `True`/`False` flags, for example user-configurable settings in an app. +This lets the value of individual bits control program logic. + +```python +>>> n = 0b0110 +>>> n & 0b0001 > 0 +False +>>> n & 0b0010 > 0 +True +``` + +For a bitwise `|` (or), a `1` is set in the output if there is a `1` in _either_ of the inputs: + +```python +>>> format(x | y, '08b') +'01101110' +``` + +There is also a `^` operator for bitwise exclusive or (xor). +In this case, a `1` is set if it appears in either of the inputs _but not both_. + +If xor `^` seems strange, be aware that this is by far the most common operation in cryptography. + +```python +>>> format(x ^ y, '08b') +'01001100' +``` + +Finally, there is the `~` operator (the tilde character), which is a bitwise `not` that takes a single input and inverts all the bits. +Each `1` changes to `0` and vice versa. + +`Bitwise ~` may give an answer you were not expecting. +See the next section for details. + +## Negative numbers + +In decimal representation, we distinguish positive and negative numbers by putting a `+` or `-` sign in front. + +Doing this at binary level proved inefficient for digital computing. +Not least, it raised the problem that `+0` is not the same as `-0`. + +Instead, all modern computers use a `twos-complement` representation for negative numbers, right down to the silicon chip level. + +This means that all bits are inverted, and a number is interpreted as negative if the left-most bit is `1`. + +As an added complication, recent versions of Python no longer use finite-integer concepts like `int32` internally. +Instead, an `int` can now be of unlimited size, and a negative or bit-inverted number has a (theoretically) infinite number of `1`'s to the left, just as a positive number has `0`'s. + +This makes it hard to give a useful example of bitwise not: + +```python +>>> format(x, '08b') +'01100110' +>>> format(~x, '08b') +'-1100111' # negative binary (not twos-complement display) + +>>> x +102 # decimal +>>> ~x +-103 +``` + +This is _not_ the `0b10011001` we would see in languages with fixed-size integers. + +In practice, Python programmers quite often use shift operators and `& | ^` with positive numbers. +Bitlise operations with negative numbers are much less common. + + + +[bitwise-operators]: https://wiki.python.org/moin/BitwiseOperators \ No newline at end of file diff --git a/concepts/bitwise-operators/links.json b/concepts/bitwise-operators/links.json index eb5fb7c38a..009c8529d0 100644 --- a/concepts/bitwise-operators/links.json +++ b/concepts/bitwise-operators/links.json @@ -1,18 +1,6 @@ [ { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." + "url": "https://wiki.python.org/moin/BitwiseOperators/", + "description": "BitwiseOperators on the Python wiki." } ] From 96ea5247279c0105332a5a9d5951959c22579fc1 Mon Sep 17 00:00:00 2001 From: Colin Leach Date: Sat, 9 Dec 2023 09:05:26 -0700 Subject: [PATCH 2/4] small fizes to about.md --- concepts/bitwise-operators/about.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/concepts/bitwise-operators/about.md b/concepts/bitwise-operators/about.md index 03e177df41..4ed714a1dd 100644 --- a/concepts/bitwise-operators/about.md +++ b/concepts/bitwise-operators/about.md @@ -133,8 +133,11 @@ This makes it hard to give a useful example of bitwise not: This is _not_ the `0b10011001` we would see in languages with fixed-size integers. +The `~` operator works as expected with `unsigned` byte or integer types. +These are supported in third-party packages such as `NumPy`, but not in core Python. + In practice, Python programmers quite often use shift operators and `& | ^` with positive numbers. -Bitlise operations with negative numbers are much less common. +Bitwise operations with negative numbers are much less common. From 0d85bfb058487f2be4365e95dc0963cd765e995b Mon Sep 17 00:00:00 2001 From: BethanyG Date: Tue, 26 Dec 2023 22:42:26 -0800 Subject: [PATCH 3/4] Proposed Edits and Links First draft of edits and links for Bitwise operations. --- concepts/bitwise-operators/.meta/config.json | 2 +- concepts/bitwise-operators/about.md | 193 ++++++++++++------- concepts/bitwise-operators/introduction.md | 21 +- concepts/bitwise-operators/links.json | 16 ++ 4 files changed, 160 insertions(+), 72 deletions(-) diff --git a/concepts/bitwise-operators/.meta/config.json b/concepts/bitwise-operators/.meta/config.json index 7e1fc38dfe..7767ff5d74 100644 --- a/concepts/bitwise-operators/.meta/config.json +++ b/concepts/bitwise-operators/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Python supports bitwise operations such as left/right shift, and, or, xor.", + "blurb": "Python supports bitwise operations such as left/right shift, and, or, xor, and not.", "authors": ["BethanyG", "colinleach"], "contributors": [] } diff --git a/concepts/bitwise-operators/about.md b/concepts/bitwise-operators/about.md index 4ed714a1dd..ce326add86 100644 --- a/concepts/bitwise-operators/about.md +++ b/concepts/bitwise-operators/about.md @@ -1,144 +1,197 @@ # About -Down at the hardware level, transistors can only be on or off: two states that we traditionaly represent with `1` and `0`. -These are `binary digits`, abbreviated as `bits`. +Down at the hardware level, transistors can only be on or off: two states that we traditionally represent with `1` and `0`. +These are the [`binary digits`][binary-digits], abbreviated as [`bits`][bits]. +Awareness of `bits` and `binary` is particularly important for systems programmers working in low-level languages. -This is particularly important for systems pprogrammers working in low-level languages. -However, for most of the history of computing the priority has been to find increasing sophisticated ways to hide the binary reality from most users. -Hence we work with `int`, `float`, `string` and many other types, up to audio and video formats. +However, for most of the history of computing the programming priority has been to find increasingly sophisticated ways to _abstract away_ this binary reality. +In Python (and many other [high-level programming languages][high-level-language]), we work with `int`, `float`, `string` and other defined _types_, up to and including audio and video formats. +We let the Python internals take care of (eventually) translating everything to bits. -Nevertheless, bitwise operations can sometimes have significant advantages in speed and memory efficiency, even in a high-level scripting language like Python. +Nevertheless, using [bitwise-operators][python-bitwise-operators] and [bitwise operations][python-bitwise-operations] can sometimes have significant advantages in speed and memory efficiency, even in a high-level language like Python. -## Entering and displaying binary numbers -Unsurprisingly, Python interacts with the user using decimal numbers by default, but the programmer can override this. +## Entering and Displaying Binary Numbers -Binary numbers are just entered with a `0b` prefix, just as `0x` can be used for hexadecimal (hex numbers are a concise way to represent groups of 4 bits). -Note that these are all really an `int`, just displayed differently. +Unsurprisingly, Python interacts with the user using decimal numbers, but a programmer can override this default. +In fact, Python will readily accept an `int` in `binary`, `hexadecimal`, or `octal` format, and will happily perform mathematical operations between them. +For more details, you can review the [concept:python/binary-octal-hexadecimal]() concept. + +Binary numbers are entered with a `0b` prefix, just as `0x` can be used for hexadecimal (_hex numbers are a concise way to represent groups of 4 bits_), and `oct` can be used for octal numbers. + +There are multiple ways to convert integers to binary strings, varying in whether they include the `0b` prefix and whether they support left-padding with zeros: -There are multiple ways to convert integers to binary strings, varying in whether they include the `0b` prefix and whether they support left-padding with zeros. ```python ->>> 0b10111 # binary entry +#Binary entry. +>>> 0b10111 23 ->>> bin(23) # int to binary string, with prefix +#Converting an int display to binary string, with prefix. +>>> bin(23) '0b10111' ->>> n = 23 ->>> format(n, '08b') # no prefix, padded to 8 digits +>>> number = 23 + +#Binary without prefix, padded to 8 digits. +>>> format(number, '08b') '00010111' ->>> f"{n} in decimal is {n:08b} in binary and {n:x} in hex" # same, but using an f-string + +#Same format, but using an f-string. +>>> f"{number} in decimal is {number:08b} in binary and {number:x} in hex" '23 in decimal is 00010111 in binary and 17 in hex' ``` -## [`Shift operators`][bitwise-operators] -The left-shift operator `x << y` simply moves all the bits in `x` by `y` places to the left, filling the new gaps with zeros. -Note that this is arithmetically identical to multiplying by `2**y`. +## [`Bitwise Logic`][bitwise-operators] -The right-shift operator `x >> y` does the opposite (for non-negative numbers, see below for how negative numbers work). -This is arithmetically identical to integer division `x // 2**y`. +In the [concept:python/bools]() concept, we discussed the _logical operators_ `and`, `or` and `not` used with Boolean (_`True` and `False`_) values. +The same logic rules apply when working with bits. -```python ->>> x = 8 ->>> format(x, '08b') -'00001000' +However, the bitwise equivalents of the logical operators `&` (_and_), `|` (_or_), `~` (_not_), and `^` (_[XOR][xor]_), are applied to each _bit_ in a binary representation, treating `1` as `True` ("on") and `0` as `False` ("off"). +An example with the bitwise `&` might make this clearer: ->>> x << 2 # left shift -32 ->>> format(x << 2, '08b') -'00100000' ->>> format(x >> 2, '08b') # right shift -'00000010' -``` - -## [`Bitwise logic`][bitwise-operators] - -In a previous concept, we saw the logical operators `and`, `or` and `not` which operate on `True` and `False` values. - -In the bitwise equivalent, the operators are applied to each bit in the number, treating `1` as `True` and `0` as `False.` -An example with bitwise `&` (and) might make this clearer: ```python >>> x = 0b01100110 >>> y = 0b00101010 + >>> format(x & y, '08b') '00100010' ``` -Only positions with a `1` in _both_ the input strings are set to `1` in the output. +Only positions with a `1` in _**both**_ the input strings are set to `1` in the output. + +Bitwise `&` is commonly used as a way to isolate single bits in a compacted set of `True`/`False` values, such as user-configurable settings in an app. +This enables the value of individual bits to control program logic: -Bitwise `&` is commonly used as a way to isolate single bits in a compacted set of `True`/`False` flags, for example user-configurable settings in an app. -This lets the value of individual bits control program logic. ```python ->>> n = 0b0110 ->>> n & 0b0001 > 0 +>>> number = 0b0110 +>>> number & 0b0001 > 0 False ->>> n & 0b0010 > 0 + +>>> number & 0b0010 > 0 True ``` -For a bitwise `|` (or), a `1` is set in the output if there is a `1` in _either_ of the inputs: + +For a bitwise `|` (or), a `1` is set in the output if there is a `1` in _**either**_ of the inputs: + ```python +>>> x = 0b01100110 +>>> y = 0b00101010 + >>> format(x | y, '08b') '01101110' ``` -There is also a `^` operator for bitwise exclusive or (xor). -In this case, a `1` is set if it appears in either of the inputs _but not both_. -If xor `^` seems strange, be aware that this is by far the most common operation in cryptography. +With the `^` operator for bitwise e**x**clusive **or** (xor), a `1` is set if it appears in _**either**_ of the inputs _**but not both**_ inputs. +This symbol might seem familiar from the [concept:python/sets] concept, where it is used for `set` _symmetric difference_, which is the same as [xor applied to sets][symmetric-difference]. +If xor `^` seems strange, be aware that this is by far the [most common operation in cryptography][xor-cipher]. + ```python +>>> x = 0b01100110 +>>> y = 0b00101010 + >>> format(x ^ y, '08b') '01001100' ``` -Finally, there is the `~` operator (the tilde character), which is a bitwise `not` that takes a single input and inverts all the bits. -Each `1` changes to `0` and vice versa. - -`Bitwise ~` may give an answer you were not expecting. -See the next section for details. -## Negative numbers +Finally, there is the `~` operator (_the [tilde][tilde] character_), which is a bitwise `not` that takes a single input and _**inverts all the bits**_, which might not be the result you were expecting! +Each `1` in the representation changes to `0`, and vice versa. +See the section below for details: -In decimal representation, we distinguish positive and negative numbers by putting a `+` or `-` sign in front. -Doing this at binary level proved inefficient for digital computing. -Not least, it raised the problem that `+0` is not the same as `-0`. +## Negative Numbers and Binary Representation -Instead, all modern computers use a `twos-complement` representation for negative numbers, right down to the silicon chip level. +In decimal representation, we distinguish positive and negative numbers by using a `+` or `-` sign to the left of the digits. +Using these symbols at a binary level proved inefficient for digital computing and raised the problem that `+0` is not the same as `-0`. -This means that all bits are inverted, and a number is interpreted as negative if the left-most bit is `1`. +Rather than using `-` and `+`, all modern computers use a [`twos-complement`][twos-complement] representation for negative numbers, right down to the silicon chip level. +This means that all bits are inverted and a number is _**interpreted as negative**_ if the left-most bit (also termed the "significant bit") is a `1`. +Positive numbers have a significant bit of `0`. +This representation has the advantage of only having one version of zero, so that the programmer doesn't have to manage `-0` and `+0`. -As an added complication, recent versions of Python no longer use finite-integer concepts like `int32` internally. -Instead, an `int` can now be of unlimited size, and a negative or bit-inverted number has a (theoretically) infinite number of `1`'s to the left, just as a positive number has `0`'s. +This way of representing negative and positive numbers adds a complication for recent versions of Python: there are no longer finite-integer concepts like `int32` or `int64` internally in the core langauge. +In 'modern' Python, `int`s are of unlimited size (_limited only by hardware capacity_), and a negative or bit-inverted number has a (_theoretically_) infinite number of `1`'s to the left, just as a positive number has unlimited `0`'s. -This makes it hard to give a useful example of bitwise not: +This makes it difficult to give a useful example of `bitwise not`: ```python +>>> x = 0b01100110 >>> format(x, '08b') '01100110' + +#This is a negative binary (not twos-complement display). >>> format(~x, '08b') -'-1100111' # negative binary (not twos-complement display) +'-1100111' + #Decimal representation. >>> x -102 # decimal +102 + +#Using the Bitwise not, with an unintuitive result. >>> ~x -103 ``` -This is _not_ the `0b10011001` we would see in languages with fixed-size integers. +This is **not** the `0b10011001` we would see in languages with fixed-size integers. -The `~` operator works as expected with `unsigned` byte or integer types. -These are supported in third-party packages such as `NumPy`, but not in core Python. +The `~` operator only works as expected with _**unsigned**_ byte or integer types, or with fixed-sized integer types. +These numeric types are supported in third-party packages such as [`NumPy`][numpy], [`pandas`][pandas], and [`sympy`][sympy] but not in core Python. -In practice, Python programmers quite often use shift operators and `& | ^` with positive numbers. +In practice, Python programmers quite often use the shift operators described below and `& | ^` with positive numbers only. Bitwise operations with negative numbers are much less common. +One technique is to add [`2**32 (or 1 << 32)`][unsigned-int-python] to a negative value to make an `int` unsigned, but this gets difficult to manage. +Another strategy is to work with the [`ctypes`][ctypes-module] module, and use c-style integer types, but this is equally unwieldy. + + +## [`Shift operators`][bitwise-shift-operators] + +The left-shift operator `x << y` simply moves all the bits in `x` by `y` places to the left, filling the new gaps with zeros. +Note that this is arithmetically identical to multiplying a number by `2**y`. + +The right-shift operator `x >> y` does the opposite. +This is arithmetically identical to integer division `x // 2**y`. +Keep in mind the previous section on negative numbers and their pitfalls when shifting. -[bitwise-operators]: https://wiki.python.org/moin/BitwiseOperators \ No newline at end of file +```python +>>> x = 8 +>>> format(x, '08b') +'00001000' + +#A left bit shift. +>>> x << 2 +32 + +>>> format(x << 2, '08b') +'00100000' + +#A right bit shift. +>>> format(x >> 2, '08b') +'00000010' +``` + +[binary-digits]: https://www.khanacademy.org/computing/computers-and-internet/xcae6f4a7ff015e7d:digital-information/xcae6f4a7ff015e7d:binary-numbers/v/the-binary-number-system +[bits]: https://en.wikipedia.org/wiki/Bit +[bitwise-shift-operators]: https://docs.python.org/3/reference/expressions.html#shifting-operations +[ctypes-module]: https://docs.python.org/3/library/ctypes.html#module-ctypes +[high-level-language]: https://en.wikipedia.org/wiki/High-level_programming_language +[numpy]: https://numpy.org/doc/stable/user/basics.types.html +[pandas]: https://pandas.pydata.org/docs/reference/arrays.html#nullable-integer +[python-bitwise-operations]: https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations +[python-bitwise-operators]: https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations +[symmetric-difference]: https://math.stackexchange.com/questions/84184/relation-between-xor-and-symmetric-difference#:~:text=It%20is%20the%20same%20thing,they%20are%20indeed%20the%20same. +[sympy]: https://docs.sympy.org/latest/modules/codegen.html#predefined-types +[tilde]: https://en.wikipedia.org/wiki/Tilde +[twos-complement]: https://en.wikipedia.org/wiki/Two%27s_complement#:~:text=Two's%20complement%20is%20the%20most,number%20is%20positive%20or%20negative. +[unsigned-int-python]: https://stackoverflow.com/a/20768199 +[xor-cipher]: https://en.wikipedia.org/wiki/XOR_cipher +[xor]: https://stackoverflow.com/a/2451393 diff --git a/concepts/bitwise-operators/introduction.md b/concepts/bitwise-operators/introduction.md index bbe12ffd5e..88aba3a6a7 100644 --- a/concepts/bitwise-operators/introduction.md +++ b/concepts/bitwise-operators/introduction.md @@ -1 +1,20 @@ -#TODO: Add introduction for this concept. +# Introduction + +Down at the hardware level, transistors can only be on or off: two states that we traditionally represent with `1` and `0`. +These are the [`binary digits`][binary-digits], abbreviated as [`bits`][bits]. +Awareness of `bits` and `binary` is particularly important for systems programmers working in low-level languages. + +However, for most of the history of computing the programming priority has been to find increasingly sophisticated ways to _abstract away_ this binary reality. + + +In Python (and many other [high-level programming languages][high-level-language]), we work with `int`, `float`, `string` and other defined _types_, up to and including audio and video formats. +We let the Python internals take care of (eventually) translating everything to bits. + + +Nevertheless, using [bitwise-operators][python-bitwise-operators] and [bitwise operations][python-bitwise-operations] can sometimes have significant advantages in speed and memory efficiency, even in a high-level language like Python. + +[high-level-language]: https://en.wikipedia.org/wiki/High-level_programming_language +[binary-digits]: https://www.khanacademy.org/computing/computers-and-internet/xcae6f4a7ff015e7d:digital-information/xcae6f4a7ff015e7d:binary-numbers/v/the-binary-number-system +[bits]: https://en.wikipedia.org/wiki/Bit +[python-bitwise-operations]: https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations +[python-bitwise-operators]: https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations diff --git a/concepts/bitwise-operators/links.json b/concepts/bitwise-operators/links.json index 009c8529d0..7c103c8463 100644 --- a/concepts/bitwise-operators/links.json +++ b/concepts/bitwise-operators/links.json @@ -2,5 +2,21 @@ { "url": "https://wiki.python.org/moin/BitwiseOperators/", "description": "BitwiseOperators on the Python wiki." + }, + { + "url": "https://realpython.com/python-bitwise-operators", + "description": "Real Python: Bitwise Operators in Python." + }, + { + "url": "https://stackoverflow.com/a/20768199", + "description": "Stack Overflow: Convert a Python int to an unsigned int." + }, + { + "url": "https://www.khanacademy.org/computing/computer-science/cryptography/ciphers/a/xor-bitwise-operation", + "description": "Khan Academy: The Ultimate Shift Cipher." + }, + { + "url": "https://en.wikipedia.org/wiki/XOR_cipher", + "description": "The XOR Cipher" } ] From 3dcfe56c43fe7d037368f473a84d89973bb8acfa Mon Sep 17 00:00:00 2001 From: BethanyG Date: Wed, 27 Dec 2023 14:14:40 -0800 Subject: [PATCH 4/4] Typos and Review Changes --- concepts/bitwise-operators/about.md | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/concepts/bitwise-operators/about.md b/concepts/bitwise-operators/about.md index ce326add86..a4ddb509c1 100644 --- a/concepts/bitwise-operators/about.md +++ b/concepts/bitwise-operators/about.md @@ -23,27 +23,27 @@ There are multiple ways to convert integers to binary strings, varying in whethe ```python -#Binary entry. +# Binary entry. >>> 0b10111 23 -#Converting an int display to binary string, with prefix. +# Converting an int display to binary string, with prefix. >>> bin(23) '0b10111' >>> number = 23 -#Binary without prefix, padded to 8 digits. +# Binary without prefix, padded to 8 digits. >>> format(number, '08b') '00010111' -#Same format, but using an f-string. +# Same format, but using an f-string. >>> f"{number} in decimal is {number:08b} in binary and {number:x} in hex" '23 in decimal is 00010111 in binary and 17 in hex' ``` -## [`Bitwise Logic`][bitwise-operators] +## [`Bitwise Logic`][python-bitwise-operations] In the [concept:python/bools]() concept, we discussed the _logical operators_ `and`, `or` and `not` used with Boolean (_`True` and `False`_) values. The same logic rules apply when working with bits. @@ -60,7 +60,7 @@ An example with the bitwise `&` might make this clearer: '00100010' ``` -Only positions with a `1` in _**both**_ the input strings are set to `1` in the output. +Only positions with a `1` in _**both**_ the input numbers are set to `1` in the output. Bitwise `&` is commonly used as a way to isolate single bits in a compacted set of `True`/`False` values, such as user-configurable settings in an app. This enables the value of individual bits to control program logic: @@ -89,7 +89,7 @@ For a bitwise `|` (or), a `1` is set in the output if there is a `1` in _**eithe With the `^` operator for bitwise e**x**clusive **or** (xor), a `1` is set if it appears in _**either**_ of the inputs _**but not both**_ inputs. -This symbol might seem familiar from the [concept:python/sets] concept, where it is used for `set` _symmetric difference_, which is the same as [xor applied to sets][symmetric-difference]. +This symbol might seem familiar from the [concept:python/sets]() concept, where it is used for `set` _symmetric difference_, which is the same as [xor applied to sets][symmetric-difference]. If xor `^` seems strange, be aware that this is by far the [most common operation in cryptography][xor-cipher]. @@ -104,7 +104,7 @@ If xor `^` seems strange, be aware that this is by far the [most common operatio Finally, there is the `~` operator (_the [tilde][tilde] character_), which is a bitwise `not` that takes a single input and _**inverts all the bits**_, which might not be the result you were expecting! Each `1` in the representation changes to `0`, and vice versa. -See the section below for details: +See the section below for details. ## Negative Numbers and Binary Representation @@ -113,11 +113,11 @@ In decimal representation, we distinguish positive and negative numbers by using Using these symbols at a binary level proved inefficient for digital computing and raised the problem that `+0` is not the same as `-0`. Rather than using `-` and `+`, all modern computers use a [`twos-complement`][twos-complement] representation for negative numbers, right down to the silicon chip level. -This means that all bits are inverted and a number is _**interpreted as negative**_ if the left-most bit (also termed the "significant bit") is a `1`. -Positive numbers have a significant bit of `0`. +This means that all bits are inverted and a number is _**interpreted as negative**_ if the left-most bit (also termed the "most significant bit", or MSB) is a `1`. +Positive numbers have an MSB of `0`. This representation has the advantage of only having one version of zero, so that the programmer doesn't have to manage `-0` and `+0`. -This way of representing negative and positive numbers adds a complication for recent versions of Python: there are no longer finite-integer concepts like `int32` or `int64` internally in the core langauge. +This way of representing negative and positive numbers adds a complication for Python: there are no finite-integer concepts like `int32` or `int64` internally in the core langauge. In 'modern' Python, `int`s are of unlimited size (_limited only by hardware capacity_), and a negative or bit-inverted number has a (_theoretically_) infinite number of `1`'s to the left, just as a positive number has unlimited `0`'s. This makes it difficult to give a useful example of `bitwise not`: @@ -127,15 +127,15 @@ This makes it difficult to give a useful example of `bitwise not`: >>> format(x, '08b') '01100110' -#This is a negative binary (not twos-complement display). +# This is a negative binary (not twos-complement display). >>> format(~x, '08b') '-1100111' - #Decimal representation. + # Decimal representation. >>> x 102 -#Using the Bitwise not, with an unintuitive result. +# Using the Bitwise not, with an unintuitive result. >>> ~x -103 ``` @@ -167,14 +167,14 @@ Keep in mind the previous section on negative numbers and their pitfalls when sh >>> format(x, '08b') '00001000' -#A left bit shift. +# A left bit shift. >>> x << 2 32 >>> format(x << 2, '08b') '00100000' -#A right bit shift. +# A right bit shift. >>> format(x >> 2, '08b') '00000010' ```