Corrections

This commit is contained in:
Antti H S Laaksonen 2017-02-04 22:10:45 +02:00
parent 1d967d537a
commit 15f11b09ec
1 changed files with 105 additions and 99 deletions

View File

@ -1,92 +1,94 @@
\chapter{Bit manipulation} \chapter{Bit manipulation}
A computer internally manipulates data All data in a program is internally stored as bits,
as bits, i.e., as numbers 0 and 1. i.e., as numbers 0 and 1.
In this chapter, we will learn how integers In this chapter, we will learn how integers
are represented as bits, and how bit operations are represented as bits, and how bit operations
can be used for manipulating them. can be used to manipulate them.
It turns out that there are many uses for It turns out that there are many uses for
bit operations in the implementation of algorithms. bit operations in algorithm programming.
\section{Bit representation} \section{Bit representation}
\index{bit representation} \index{bit representation}
The \key{bit representation} of a number Every nonnegative integer can be represented as a sum
indicates which powers of two form the number. \[c_k 2^k + \ldots + c_2 2^2 + c_1 2^1 + c_0 2^0,\]
For example, the bit representation of the number 43 where each coefficient $c_i$ is either 0 or 1,
is 101011 because and the bit representation of such a number is
$43 = 2^5 + 2^3 + 2^1 + 2^0$ where $c_k \cdots c_2 c_1 c_0$.
bits 0, 1, 3 and 5 from the right are ones, For example, the number 43 corresponds to the sum
and all other bits are zeros. \[1 \cdot 2^5 + 0 \cdot 2^4 + 1 \cdot 2^3 + 0 \cdot 2^2 + 1 \cdot 2^1 + 1 \cdot 2^0,\]
so the bit representation of the number is 101011.
The length of a bit representation of a number In programming, the length of the bit representation
in a computer is static, and depends on the depends on the data type chosen.
data type chosen. For example, in C++ the type \texttt{int} is
For example, the \texttt{int} type in C++ is usually a 32-bit type and an \texttt{int} number
usually a 32-bit type, and an \texttt{int} number
consists of 32 bits. consists of 32 bits.
In this case, the bit representation of 43 Thus, the bit representation of 43
as an \texttt{int} number is as follows: as an \texttt{int} number is as follows:
\[00000000000000000000000000101011\] \[00000000000000000000000000101011\]
The bit representation of a number is either The bit representation of a number is either
\key{signed} or \key{unsigned}. \key{signed} or \key{unsigned}.
The first bit of a signed number is the sign Usually a signed representation is used,
($+$ or $-$), and we can represent numbers which means that both negative and positive
$-2^{n-1} \ldots 2^{n-1}-1$ using $n$ bits. numbers can be represented.
In an unsigned number, in turn, A signed number of $n$ bits can contain any
all bits belong to the number and we integer between $2^{n-1}$ and $2^{n-1}-1$.
can represent numbers $0 \ldots 2^n-1$ using $n$ bits. For example, the \texttt{int} type in C++ is
a signed type, and it can contain any
integer between $2^{31}$ and $2^{31}-1$.
In an signed bit representation, The first bit in a signed representation
the first bit of a nonnegative number is 0, is the sign of the number (0 for nonnegative numbers
and the first bit of a negative number is 1. and 1 for negative numbers), and
\key{Two's complement} is used which means that the remaining $n-1$ bits contain the value of the number.
the opposite number of a number can be calculated \key{Two's complement} is used, which means that the
by first inversing all the bits in the number, opposite number of a number is calculated by first
inverting all the bits in the number,
and then increasing the number by one. and then increasing the number by one.
For example, the representation of $-43$ For example, the bit representation of $-43$
as an \texttt{int} number is as follows: as an \texttt{int} number is as follows:
\[11111111111111111111111111010101\] \[11111111111111111111111111010101\]
The connection between signed and unsigned numbers In a signed representation, only nonnegative
is that the representations of a signed numbers can be used, but the upper bound of the numbers is larger.
number $-x$ and an unsigned number $2^n-x$ A signed number of $n$ bits can contain any
are equal. integer between $0$ and $2^n-1$.
Thus, the above representation corresponds to For example, the \texttt{unsigned int} type in C++
the unsigned number $2^{32}-43$. can contain any integer between $0$ and $2^{32}-1$.
In C++, the numbers are signed as default, There is a connection between signed and unsigned
but we can create unsigned numbers by representations:
using the keyword \texttt{unsigned}. a number $-x$ in a signed representation
For example, in the code equals the number $2^n-x$ in an unsigned representation.
For example, the following code shows that
the signed number $x=-43$ equals the unsigned
number $y=2^{32}-43$:
\begin{lstlisting} \begin{lstlisting}
int x = -43; int x = -43;
unsigned int y = x; unsigned int y = x;
cout << x << "\n"; // -43 cout << x << "\n"; // -43
cout << y << "\n"; // 4294967253 cout << y << "\n"; // 4294967253
\end{lstlisting} \end{lstlisting}
the signed number
$x=-43$ becomes the unsigned number $y=2^{32}-43$.
If a number becomes too large or too small for the If a number is larger than the upper bound
bit representation chosen, it will overflow. of the bit representation, the number will overflow.
In practice, in a signed representation, In a signed representation,
the next number after $2^{n-1}-1$ is $-2^{n-1}$, the next number after $2^{n-1}-1$ is $-2^{n-1}$,
and in an unsigned representation, and in an unsigned representation,
the next number after $2^{n-1}$ is $0$. the next number after $2^{n-1}$ is $0$.
For example, in the code For example, in the following code,
the next number after $2^{31}-1$ is $-2^{31}$:
\begin{lstlisting} \begin{lstlisting}
int x = 2147483647 int x = 2147483647
cout << x << "\n"; // 2147483647 cout << x << "\n"; // 2147483647
x++; x++;
cout << x << "\n"; // -2147483648 cout << x << "\n"; // -2147483648
\end{lstlisting} \end{lstlisting}
we increase $2^{31}-1$ by one to get $-2^{31}$.
\section{Bit operations} \section{Bit operations}
@ -97,9 +99,9 @@ we increase $2^{31}-1$ by one to get $-2^{31}$.
\index{and operation} \index{and operation}
The \key{and} operation $x$ \& $y$ produces a number The \key{and} operation $x$ \& $y$ produces a number
that has bit 1 in positions where both the numbers that has one bits in positions where both
$x$ and $y$ have bit 1. $x$ and $y$ have one bits.
For example, $22$ \& $26$ = 18 because For example, $22$ \& $26$ = 18, because
\begin{center} \begin{center}
\begin{tabular}{rrr} \begin{tabular}{rrr}
@ -114,16 +116,17 @@ Using the and operation, we can check if a number
$x$ is even because $x$ is even because
$x$ \& $1$ = 0 if $x$ is even, and $x$ \& $1$ = 0 if $x$ is even, and
$x$ \& $1$ = 1 if $x$ is odd. $x$ \& $1$ = 1 if $x$ is odd.
More generally, $x$ is divisible by $2^k$
exactly when $x$ \& $(2^k-1)$ = 0.
\subsubsection{Or operation} \subsubsection{Or operation}
\index{or operation} \index{or operation}
The \key{or} operation $x$ | $y$ produces a number The \key{or} operation $x$ | $y$ produces a number
that has bit 1 in positions where at least one that has one bits in positions where at least one
of the numbers of $x$ and $y$ have one bits.
$x$ and $y$ have bit 1. For example, $22$ | $26$ = 30, because
For example, $22$ | $26$ = 30 because
\begin{center} \begin{center}
\begin{tabular}{rrr} \begin{tabular}{rrr}
@ -139,10 +142,9 @@ For example, $22$ | $26$ = 30 because
\index{xor operation} \index{xor operation}
The \key{xor} operation $x$ $\XOR$ $y$ produces a number The \key{xor} operation $x$ $\XOR$ $y$ produces a number
that has bit 1 in positions where exactly one that has one bits in positions where exactly one
of the numbers of $x$ and $y$ have one bits.
$x$ and $y$ have bit 1. For example, $22$ $\XOR$ $26$ = 12, because
For example, $22$ $\XOR$ $26$ = 12 because
\begin{center} \begin{center}
\begin{tabular}{rrr} \begin{tabular}{rrr}
@ -159,12 +161,12 @@ $\XOR$ & 11010 & (26) \\
The \key{not} operation \textasciitilde$x$ The \key{not} operation \textasciitilde$x$
produces a number where all the bits of $x$ produces a number where all the bits of $x$
have been inversed. have been inverted.
The formula \textasciitilde$x = -x-1$ holds, The formula \textasciitilde$x = -x-1$ holds,
for example, \textasciitilde$29 = -30$. for example, \textasciitilde$29 = -30$.
The result of the not operation at the bit level The result of the not operation at the bit level
depends on the length of the bit representation depends on the length of the bit representation,
because the operation changes all bits. because the operation changes all bits.
For example, if the numbers are 32-bit For example, if the numbers are 32-bit
\texttt{int} numbers, the result is as follows: \texttt{int} numbers, the result is as follows:
@ -180,60 +182,64 @@ $x$ & = & 29 & 00000000000000000000000000011101 \\
\index{bit shift} \index{bit shift}
The left bit shift $x < < k$ produces a number The left bit shift $x < < k$ appends $k$
where the bits of $x$ have been moved $k$ steps to zeros to the end of the number,
the left by adding $k$ zero bits to the number.
The right bit shift $x > > k$ produces a number
where the bits of $x$ have been moved $k$ steps
to the right by removing $k$ last bits from the number.
For example, $14 < < 2 = 56$
because $14$ equals 1110,
and it becomes $56$ that equals 111000.
Correspondingly, $49 > > 3 = 6$
because $49$ equals 110001,
and it becomes $6$ that equals 110.
Note that the left bit shift $x < < k$
corresponds to multiplying $x$ by $2^k$,
and the right bit shift $x > > k$ and the right bit shift $x > > k$
removes the $k$ last bits from the number.
For example, $14 < < 2 = 56$,
because $14$ equals 1110
and $56$ equals 111000.
Similarily, $49 > > 3 = 6$,
because $49$ equals 110001
and $6$ equals 110.
Note that $x < < k$
corresponds to multiplying $x$ by $2^k$,
and $x > > k$
corresponds to dividing $x$ by $2^k$ corresponds to dividing $x$ by $2^k$
rounding downwards. rounded down to an integer.
\subsubsection{Bit manipulation} \subsubsection{Applications}
The bits in a number are indexed from the right A number of the form $1 < < k$ has a one bit
to the left beginning from zero.
A number of the form $1 < < k$ contains a one bit
in position $k$, and all other bits are zero, in position $k$, and all other bits are zero,
so we can manipulate single bits of numbers so we can use such numbers to access single bits of numbers.
using these numbers. For example, the $k$th bit of a number is one
exactly when $x$ \& $(1 < < k)$ is not zero.
The following code prints the bit representation
of an \texttt{int} number $x$:
The $k$th bit in $x$ is one if \begin{lstlisting}
$x$ \& $(1 < < k) = (1 < < k)$. for (int i = 31; i >= 0; i--) {
The formula $x$ | $(1 < < k)$ if (x&(1<<i)) cout << "1";
else cout << "0";
}
\end{lstlisting}
It is also possible to modify single bits
of numbers using a similar idea.
For example, the expression $x$ | $(1 < < k)$
sets the $k$th bit of $x$ to one, sets the $k$th bit of $x$ to one,
the formula the expression
$x$ \& \textasciitilde $(1 < < k)$ $x$ \& \textasciitilde $(1 < < k)$
sets the $k$th bit of $x$ to zero, sets the $k$th bit of $x$ to zero,
and the formula and the expression
$x$ $\XOR$ $(1 < < k)$ $x$ $\XOR$ $(1 < < k)$
inverses the $k$th bit of $x$. inverts the $k$th bit of $x$.
The formula $x$ \& $(x-1)$ sets the last The formula $x$ \& $(x-1)$ sets the last
one bit of $x$ to zero, one bit of $x$ to zero,
and the formula $x$ \& $-x$ sets all the and the formula $x$ \& $-x$ sets all the
one bits to zero, except for the last one bit. one bits to zero, except for the last one bit.
The formula $x$ | $(x-1)$, in turn, The formula $x$ | $(x-1)$
inverses all the bits after the last one bit. inverts all the bits after the last one bit.
Also note that a positive number $x$ is Also note that a positive number $x$ is
of the form $2^k$ if $x$ \& $(x-1) = 0$. of the form $2^k$ if $x$ \& $(x-1) = 0$.
\subsubsection*{Additional functions} \subsubsection*{Additional functions}
The g++ compiler contains the following The g++ compiler provides the following
functions for bit manipulation: functions for counting bits:
\begin{itemize} \begin{itemize}
\item \item
@ -251,7 +257,7 @@ the parity (even or odd) of the number of ones
\end{itemize} \end{itemize}
\begin{samepage} \begin{samepage}
The following code shows how to use the functions: The functions can be used as follows:
\begin{lstlisting} \begin{lstlisting}
int x = 5328; // 00000000000000000001010011010000 int x = 5328; // 00000000000000000001010011010000
cout << __builtin_clz(x) << "\n"; // 19 cout << __builtin_clz(x) << "\n"; // 19
@ -261,12 +267,12 @@ cout << __builtin_parity(x) << "\n"; // 1
\end{lstlisting} \end{lstlisting}
\end{samepage} \end{samepage}
The functions support \texttt{int} numbers, The functions can be used with \texttt{int} numbers,
but there are also \texttt{long long} versions but there are also \texttt{long long} versions
of the functions of the functions
available with the prefix \texttt{ll}. available with the prefix \texttt{ll}.
\section{Bit representation of sets} \section{Representing sets}
Each subset of a set $\{0,1,2,\ldots,n-1\}$ Each subset of a set $\{0,1,2,\ldots,n-1\}$
corresponds to a $n$ bit number corresponds to a $n$ bit number