Corrections

This commit is contained in:
Antti H S Laaksonen 2017-02-16 23:31:26 +02:00
parent d1dc9063f3
commit c215e415cd
1 changed files with 62 additions and 46 deletions

View File

@ -1,6 +1,6 @@
\chapter{Bit manipulation} \chapter{Bit manipulation}
All data in a program is internally stored as bits, All data in computer programs is internally stored 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
@ -14,15 +14,15 @@ bit operations in algorithm programming.
Every nonnegative integer can be represented as a sum Every nonnegative integer can be represented as a sum
\[c_k 2^k + \ldots + c_2 2^2 + c_1 2^1 + c_0 2^0,\] \[c_k 2^k + \ldots + c_2 2^2 + c_1 2^1 + c_0 2^0,\]
where each coefficient $c_i$ is either 0 or 1, where each coefficient $c_i$ is either 0 or 1.
and the bit representation of such a number is The bit representation of such a number is
$c_k \cdots c_2 c_1 c_0$. $c_k \cdots c_2 c_1 c_0$.
For example, the number 43 corresponds to the sum For example, the number 43 corresponds to the sum
\[1 \cdot 2^5 + 0 \cdot 2^4 + 1 \cdot 2^3 + 0 \cdot 2^2 + 1 \cdot 2^1 + 1 \cdot 2^0,\] \[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. so the bit representation of the number is 101011.
In programming, the length of the bit representation In programming, the length of the bit representation
depends on the data type chosen. depends on the data type of the number.
For example, in C++ the type \texttt{int} is For example, in C++ the type \texttt{int} 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.
@ -44,7 +44,7 @@ integer between $2^{31}$ and $2^{31}-1$.
The first bit in a signed representation The first bit in a signed representation
is the sign of the number (0 for nonnegative numbers is the sign of the number (0 for nonnegative numbers
and 1 for negative numbers), and and 1 for negative numbers), and
the remaining $n-1$ bits contain the value of the number. the remaining $n-1$ bits contain the magnitude of the number.
\key{Two's complement} is used, which means that the \key{Two's complement} is used, which means that the
opposite number of a number is calculated by first opposite number of a number is calculated by first
inverting all the bits in the number, inverting all the bits in the number,
@ -81,8 +81,7 @@ 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 following code, For example, consider 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
@ -90,6 +89,12 @@ x++;
cout << x << "\n"; // -2147483648 cout << x << "\n"; // -2147483648
\end{lstlisting} \end{lstlisting}
Initially, the value of $x$ is $2^{31}-1$.
This is the largest number that can be stored
in an \texttt{int} variable,
so the next number after $2^{31}-1$ is $-2^{31}$.
\section{Bit operations} \section{Bit operations}
\newcommand\XOR{\mathbin{\char`\^}} \newcommand\XOR{\mathbin{\char`\^}}
@ -183,7 +188,7 @@ $x$ & = & 29 & 00000000000000000000000000011101 \\
\index{bit shift} \index{bit shift}
The left bit shift $x < < k$ appends $k$ The left bit shift $x < < k$ appends $k$
zeros to the end of the number, zero bits to the number,
and the right bit shift $x > > k$ and the right bit shift $x > > k$
removes the $k$ last bits from the number. removes the $k$ last bits from the number.
For example, $14 < < 2 = 56$, For example, $14 < < 2 = 56$,
@ -202,7 +207,7 @@ rounded down to an integer.
\subsubsection{Applications} \subsubsection{Applications}
A number of the form $1 < < k$ has a one bit A number of the form $1 < < k$ has a one bit
in position $k$, and all other bits are zero, in position $k$ and all other bits are zero,
so we can use such numbers to access single bits of numbers. so we can use such numbers to access single bits of numbers.
For example, the $k$th bit of a number is one For example, the $k$th bit of a number is one
exactly when $x$ \& $(1 < < k)$ is not zero. exactly when $x$ \& $(1 < < k)$ is not zero.
@ -217,7 +222,7 @@ for (int i = 31; i >= 0; i--) {
\end{lstlisting} \end{lstlisting}
It is also possible to modify single bits It is also possible to modify single bits
of numbers using a similar idea. of numbers using the above idea.
For example, the expression $x$ | $(1 < < k)$ 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 expression the expression
@ -267,27 +272,27 @@ cout << __builtin_parity(x) << "\n"; // 1
\end{lstlisting} \end{lstlisting}
\end{samepage} \end{samepage}
The functions can be used with \texttt{int} numbers, The above functions support \texttt{int} numbers,
but there are also \texttt{long long} versions but there are also \texttt{long long} functions
of the functions available with the suffix \texttt{ll}.
available with the prefix \texttt{ll}.
\section{Representing 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 an $n$ bit number
where the one bits indicate which elements where the one bits indicate which elements
are included in the subset. are included in the subset.
For example, the bit representation of $\{1,3,4,8\}$ For example, the set $\{1,3,4,8\}$
is 100011010 that equals $2^8+2^4+2^3+2^1=282$. corresponds to the number $2^8+2^4+2^3+2^1=282$,
whose bit representation is 100011010.
The benefit in using a bit representation is The benefit in using the bit representation
that the information whether an element belongs is that the information whether an element belongs
to the set requires only one bit of memory. to the set requires only one bit of memory.
In addition, we can implement set operations In addition, set operations can be efficiently
efficiently as bit operations. implemented as bit operations.
\subsubsection{Set operations} \subsubsection{Set implementation}
In the following code, $x$ In the following code, $x$
contains a subset of $\{0,1,2,\ldots,31\}$. contains a subset of $\{0,1,2,\ldots,31\}$.
@ -309,6 +314,14 @@ for (int i = 0; i < 32; i++) {
cout << "\n"; cout << "\n";
\end{lstlisting} \end{lstlisting}
The output of the code is as follows:
\begin{lstlisting}
1 3 4 8
\end{lstlisting}
\subsubsection{Set operations}
Set operations can be implemented as follows: Set operations can be implemented as follows:
\begin{itemize} \begin{itemize}
\item $a$ \& $b$ is the intersection $a \cap b$ of $a$ and $b$ \item $a$ \& $b$ is the intersection $a \cap b$ of $a$ and $b$
@ -318,7 +331,7 @@ Set operations can be implemented as follows:
$a \setminus b$ of $a$ and $b$ $a \setminus b$ of $a$ and $b$
\end{itemize} \end{itemize}
The following code constructs the union For example, the following code constructs the union
of $\{1,3,4,8\}$ and $\{3,6,8,9\}$: of $\{1,3,4,8\}$ and $\{3,6,8,9\}$:
\begin{lstlisting} \begin{lstlisting}
@ -335,6 +348,12 @@ for (int i = 0; i < 32; i++) {
cout << "\n"; cout << "\n";
\end{lstlisting} \end{lstlisting}
The output of the code is as follows:
\begin{lstlisting}
1 3 4 6 8 9
\end{lstlisting}
\subsubsection{Iterating through subsets} \subsubsection{Iterating through subsets}
The following code goes through The following code goes through
@ -368,17 +387,18 @@ do {
\subsubsection{From permutations to subsets} \subsubsection{From permutations to subsets}
Using dynamic programming, it is often possible Using dynamic programming, it is often possible
to turn an iteration over permutations into to change an iteration over permutations into
an iteration over subsets so that an iteration over subsets, so that
the dynamic programming state the dynamic programming state
contains a subset of a set and possibly contains a subset of a set and possibly
some additional information. some additional information.
The benefit in this is that The benefit in this is that
$n!$, the number of permutations of an $n$ element set, $n!$, the number of permutations of an $n$ element set,
is much larger than $2^n$, the number of subsets. is much larger than $2^n$, the number of subsets
of the same set.
For example, if $n=20$, then For example, if $n=20$, then
$n!=2432902008176640000$ and $2^n=1048576$. $n! \approx 2.4 \cdot 10^{18}$ and $2^n \approx 10^6$.
Hence, for certain values of $n$, Hence, for certain values of $n$,
we can efficiently go through subsets but not through permutations. we can efficiently go through subsets but not through permutations.
@ -391,36 +411,32 @@ For example, when $n=4$, there are two such permutations:
$(1,3,0,2)$ and $(2,0,3,1)$. $(1,3,0,2)$ and $(2,0,3,1)$.
Let $f(x,k)$ denote the number of valid permutations Let $f(x,k)$ denote the number of valid permutations
of $x$ where the last element is $k$ and of a subset $x$ where the last element is $k$ and
the difference between any two successive the difference between any two consecutive
elements is larger than one. elements is larger than one.
For example, $f(\{0,1,3\},1)=1$, For example, $f(\{0,1,3\},1)=1$,
because there is a permutation $(0,3,1)$, because there is a permutation $(0,3,1)$,
and $f(\{0,1,3\},3)=0$, because 0 and 1 and $f(\{0,1,3\},3)=0$, because 0 and 1
cannot be next to each other. cannot be next to each other.
Using $f$, the solution to the problem equals Using $f$, the answer to the problem equals
\[ \sum_{i=0}^{n-1} f(\{0,1,\ldots,n-1\},i), \]
\[ \sum_{i=0}^{n-1} f(\{0,1,\ldots,n-1\},i). \] because the permutation has to contain all
elements $\{0,1,\ldots,n-1\}$ and the last
\noindent element can be any element.
The dynamic programming states can be stored as follows:
The dynamic programming values can be stored as follows:
\begin{lstlisting} \begin{lstlisting}
long long d[1<<n][n]; long long d[1<<n][n];
\end{lstlisting} \end{lstlisting}
\noindent
First, $f(\{k\},k)=1$ for all values of $k$: First, $f(\{k\},k)=1$ for all values of $k$:
\begin{lstlisting} \begin{lstlisting}
for (int i = 0; i < n; i++) d[1<<i][i] = 1; for (int i = 0; i < n; i++) d[1<<i][i] = 1;
\end{lstlisting} \end{lstlisting}
\noindent
Then, the other values can be calculated Then, the other values can be calculated
as follows: as follows:
\begin{lstlisting} \begin{lstlisting}
for (int b = 0; b < (1<<n); b++) { for (int b = 0; b < (1<<n); b++) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
@ -433,9 +449,9 @@ for (int b = 0; b < (1<<n); b++) {
} }
\end{lstlisting} \end{lstlisting}
\noindent In the above code,
The variable $b$ goes through all subsets, and each the variable $b$ goes through all subsets and each
permutation is of the form $(\ldots,j,i)$ permutation is of the form $(\ldots,j,i)$,
where the difference between $i$ and $j$ is where the difference between $i$ and $j$ is
larger than one and $i$ and $j$ belong to $b$. larger than one and $i$ and $j$ belong to $b$.
@ -451,8 +467,8 @@ for (int i = 0; i < n; i++) {
\subsubsection{Sums of subsets} \subsubsection{Sums of subsets}
Finally, we consider the following problem: As the last example, we consider the following problem:
Every subset $x$ Each subset $x$
of $\{0,1,\ldots,n-1\}$ of $\{0,1,\ldots,n-1\}$
is assigned a value $c(x)$, is assigned a value $c(x)$,
and our task is to calculate for and our task is to calculate for
@ -460,8 +476,8 @@ each subset $x$ the sum
\[s(x)=\sum_{y \subset x} c(y).\] \[s(x)=\sum_{y \subset x} c(y).\]
Using bit operations, the corresponding sum is Using bit operations, the corresponding sum is
\[s(x)=\sum_{y \& x = y} c(y).\] \[s(x)=\sum_{y \& x = y} c(y).\]
The following table shows an example of For example, the functions could be
the functions when $n=3$: as follows when $n=3$:
\begin{center} \begin{center}
\begin{tabular}{rrr} \begin{tabular}{rrr}
$x$ & $c(x)$ & $s(x)$ \\ $x$ & $c(x)$ & $s(x)$ \\