For better readability, you may preferthis: vector< complex > zlist; The pair class template takes two type arguments.. To create an ordered pairwhere the first entry is a real number an
Trang 1One may think of a template as a procedure schema When the C++ compiler countersmax_of_threein a program, it uses the template to create the appropriateversion.
en-For example, here is amainthat utilizes the adaptable nature ofmax_of_three
The output of thismainis as we expect
The max of 3.4, -4.1, 11.2 is 11.2
The max of 14, 17, 0 is 17
Themax_of_threetemplate works for any typeTfor which<is defined If<
is not defined for the type, the compiler generates an error message For example,consider the followingmain
Trang 2When we attempt to compile this program, we get the following error messages (yourcomputer might produce different error messages).
max_of_three.h: In function ‘T max_of_three(T, T, T) [with T =
std::complex<double>]’:
main.cc:12: instantiated from here
max_of_three.h:6: error: no match for ‘std::complex<double>& <
argu-It is possible to create templates with multiple type parameters Such templateslook like this:
template <class A, class B>
void do_something(A arg1, B arg2) { }
When the compiler encounters code such as
long alpha = 4;
double beta = 4.5;
do_something(alpha, beta);
it creates and uses a version ofdo_somethingin whichAstands forlongandB
stands fordouble
12.2.1 Using class templates
In Section 2.7 we showed how to declare C++ variables to hold complex numbers.After the directive#include <complex>, we have statements such as these:
complex<double> w(-3.4, 5.1);
complex<long> z(4, -7);
The first declares a complex variablew in which the real and imaginary parts are
double real numbers and the second declares zto be a Gaussian integer (long
integer real and imaginary parts)
The class complex is, in fact, a class template By specifying different typesbetween the<and>delimiters, we create different classes For example, we coulduse theModtype (see Chapter 9):
Trang 3Likewise,vectoris a class template To create avectorthat contains integers,
we usevector<long> To create avectorcontaining complex numbers with realcoefficients, the following mildly baroque construction is required,
vector<complex<double> > zlist;
Note the space between the two closing>delimiters; the space is mandatory here
If it were omitted, the>>would look like the operator we use in expressions such
ascin >> xcausing angst for the compiler For better readability, you may preferthis:
vector< complex<double> > zlist;
The pair class template takes two type arguments To create an ordered pairwhere the first entry is a real number and the second is a Boolean, we write this:pair<double,bool> P;
Using class templates is straightforward The template is transformed into a cific class by adding the needed type argument(s) between the<and>delimiters.The main pitfall to avoid is supplying a type that is incompatible with the tem-plate For example, it would not make sense to declare a variable to be of type
spe-complex<PTriple>
By the way: The use of<and>delimiters in#include <iostream>is unrelated
to their use in templates
12.2.2 Creating class templates
Now that we have examined how to use class templates we are led to the issue:How do we create class templates? The technique is similar to that of creating pro-cedure templates To demonstrate the process, we create our own, extremely limitedversion of thecomplextemplate that we callmycomplex The template resides in
a file namedmycomplex.h; there is nomycomplex.ccfile Here is the header filecontaining the template
Trang 4Program 12.2: The template for the mycomplex classes.
30 T re() const { return real_part; }
31 T im() const { return imag_part; }
32
33 };
34
35 template<class T>
36 ostream& operator<<(ostream& os, const mycomplex<T>& z) {
37 os << "(" << z.re() << ") + (" << z.im() << ")i";
Let’s examine this code
• The initial template <class T> serves the same purpose as in the case
of template procedures This establishes Tas a parameter specifying a type.When we declare a variable with a statement like this
Trang 5mycomplex<double> w;
theTstands for the typedouble See lines 7–8
• The class template has two private data fields: real_partandimag_part.These are declared as typeT Thus ifwis declared typemycomplex<double>
thenw.real_partandw.imag_partare both typedouble See lines 10–12
• Three constructors are given The same name is used for these constructors:
mycomplex<T> (The<T>is optional here; the constructors could be namedsimplymycomplexwith the<T>implicitly added.)
The zero-argument constructor creates the complex number 0 + 0i Note thatthe value 0 is explicitly converted to type T This requires that type T beable to convert a zero into type T If some_typeis a class that does nothave a single-argument numerical constructor, then declaring a variable to be
amycomplex<some_type>causes a compiler error See lines 15–18.The single- and double-argument constructors follow (lines 20–28) They areself-explanatory
• We provide the methodsre()andim()to retrieve amycomplexvariable’sreal and imaginary parts Note that the return type of these methods isT Seelines 30–31
• The last part of the filemycomplex.his theoperator<<procedure for ing mycomplexvariables to the computer’s screen This procedure is not amember of themycomplexclass template, so it needs a separate introductory
writ-template <class T>in front of the procedure’s definition See line 35.The next line looks like the usual declaration of the<<operator The secondargument’s type is a reference to a variable of typemycomplex<T>
After this comes the inline code for the procedure The keywordinlineisoptional because all templates must be defined inline (If we want to includethe keyword inline, it would follow template <class T> and precede
Trang 624 T1 re() const { return real_part; }
25 T2 im() const { return imag_part; }
26
27 };
28
29 template<class T1, class T2>
30 ostream& operator<<(ostream& os, const mycomplex<T1,T2>& z) {
31 os << "(" << z.re() << ") + (" << z.im() << ")i";
32 return os;
33 }
If we use this alternativemycomplextemplate, variable declarations require thespecification of two types, such as this:
mycomplex<long, double> mixed_up_z;
Our goal is to create a C++ class template to represent polynomials over any field
Kand we call this class templatePolynomial Consider the following declarations,Polynomial<double> P;
Polynomial< complex<double> > Q;
Polynomial<Mod> R;
These are to create polynomials in R[x], C[x], and Zp[x], respectively (Of course,
we need#include <complex>and#include "Mod.h".)
Trang 712.3.1 Data
We need to store the coefficients of the polynomial For this, we use avector
variable (see Section 8.4) namedcoef The coefficient of xkis held incoef[k] Wetherefore require the directive#include <vector>in the filePolynomial.h
We hold the degree of the polynomial in alongvariable nameddg The degree isthe largest index k such thatcoef[k]is nonzero In the case where the polynomial
is equal to zero, we setdgequal to −1
See lines 11–12 in Program 12.4
12.3.2 Constructors
A basic, zero-argument constructor produces the zero polynomial This is plished by a call to aclear() method that resizes coefto hold only one value,sets that value to zero, and setsdgequal to −1 See lines 23–25 and 78–81 of Pro-gram 12.4
accom-A single-argument constructor is used to produce a constant polynomial; that is, apolynomial in which ck= 0 for all k ≥ 1 This constructor may be used explicitly orimplicitly to convert scalar values to polynomials For example, consider this code:Polynomial<double> P(5.);
for storage inQ Similarly,-M_PIis a real number and this needs to be converted to
a complex type for storage inR
To do this, we allow the argument to be of any type and then cast that argument totypeK Let’s look at the full code for this constructor (lines 27–33):
struc-Polynomial< complex<double> > Q;
Q = val;
the variablevalmay be of any type
Trang 8There is, of course, a catch We assigncoef[0]with the valueK(a) This is anexplicit request to convert the valueato type K This is fine if we are converting
alongto adoubleor adoubleto acomplex<double>, but fails whenais notconvertible to typeK, for example, ifKwere typedoubleandawere typePTriple.Notice the call to the private methoddeg_check() This method scans the dataheld incoefto find the last nonzero value and resetsdgaccordingly Various opera-tions on polynomials might alter their degree (e.g., addition of polynomials, changingcoefficients, etc.) and this method makes suredgholds the correct value
Next we have a three-argument constructor (lines 35–43) To create the mial ax2+ bx + c one simply invokesPolynomial<K>(a,b,c) As before, thethree arguments need not be typeK; it is enough that they be convertible to typeK.For example, consider this code
complex<double> b(4.,-3.);
Polynomial< complex<double> > P(a,b,c);
This creates a polynomialPequal to 7x2+ (4 − 3i)x + π
Finally, it is useful to be able to create a polynomial given an array of coefficients.The constructor on lines 45–60 takes two arguments: the size of an array and anarray of coefficients The array is declared as typeJ*; that is, an array of elements
of typeJ The only requirement onJis that values of that type must be convertible
to typeK
12.3.3 Get and set methods
We include an assortment of methods to inspect and modify the coefficients held
in aPolynomial
• Thedeg()method returns the degree of the polynomial (See line 62.)
• Theget(k)method returns the coefficient of xk In the case where k is invalid(negative or greater than the degree), we return zero (See lines 64–67.)
As an alternative toget(k)we provideoperator[](line 69) For a mialP, bothP[k]andP.get(k)have the same effect However, we have notset upoperator[]to work on the left-hand side of an assignment; we cannotchange the kth coefficient by a statement such asP[k]=c;
polyno-• TheisZero()method returns true if the polynomial is identically zero Seeline 89
• Theset(idx,a)method sets the coefficientcoef[idx]equal to the value
a See lines 71–76
Trang 9Some care must be taken here First, ifidxis negative, no action is taken If
idxis greater than the degree, we need to expandcoefaccordingly Also, thismethod might set the highest coefficient to zero, so we invokedeg_check()
• Theclear()method sets all coefficients to zero See lines 78–82
• Theminimize()method frees up any wasted memory held in coef It isconceivable that a polynomial may at one point have large degree (causing
coefto expand) and then later have small degree Although the size ofcoef
grows and shrinks with the degree, the capacity ofcoefwould remain large.This method causes thevectormethodreserveto be invoked forcoef Seelines 84–87
• Finally, we have theshift(n)method See lines 91–105
If n is positive, this has the effect of multiplying the polynomial by xn Eachcoefficient is shifted upwards; the coefficient of xk before the shift becomesthe coefficient of xk+nafter
Shifting with a negative index has the opposite effect Coefficients are moved
to lower powers of x Coefficients shifted to negative positions are discarded
The polynomialP 4x2+ 6x − 2AfterP.shift(2) 4x4+ 6x3− 2x2AfterP.shift(-1) 4x + 6
Notice that we give the argumentna default value of 1 (see line 91) Thus
P.shift()is the same asP.shift(1)
12.3.4 Function methods
Polynomials are functions and to use them as such we provide a method named
of Invoking P.of(a) evaluates the polynomial p(x) at x = a See lines 109–118
An efficient way to evaluate a polynomial such as 3x4+ 5x3− 6x2+ 2x + 7 at x = a
is this:
(3 × a) + 5 × a + (−6)×a + 2
Because polynomials are functions, they may be composed and the result is again
a polynomial We use the same method names,ofandoperator(), for polynomialcomposition For polynomialsPandQ, the result ofP.of(Q)(and alsoP(Q)) is thepolynomial p(q(x)) See lines 122–135
These methods depend on the ability to do polynomial arithmetic, and we describethose methods below (Subsection 12.3.6)
Trang 1012.3.5 Equality
To check if two polynomials are equal, we make sure they have the same degreeand that corresponding coefficients are equal The operators==and!=are given onlines 139–149
12.3.6 Arithmetic
We provide methods for the usual arithmetic operators: addition, subtraction, tiplication, and division (quotient and remainder) See lines 153ff
mul-Each of the basic operators is defined like this:
Polynomial<K> operator+(const Polynomial<K>& that) const { }
IfPandQare of typePolynomial<double>, then the expressionP+Qinvokes thismethod withthatreferring toQ However, the expressionP+5also engages thismethod; implicitly the5 is cast to a polynomial via Polynomial<double>(5).However, the expression5+Pcannot be handled by this method (because5is not apolynomial) Therefore, we also provide procedure templates such as this:
template <class J, class K>
Polynomial<K> operator+(J x, const Polynomial<K>& P) {
With the exception of division, the code for these various operators is reasonablystraightforward Division requires a bit more attention
As in the case of integers, division of polynomials produces two results: the tient and the remainder Let a(x) and b(x) be polynomials with b 6= 0 Then thereexist polynomials q(x) and r(x) for which
quo-a(x) = q(x)b(x) + r(x) and deg r(x) < deg b(x)
Furthermore, q and r are unique For example, if a(x) = 3x2+x−2 and b(x) = 2x+1,then q(x) =32x−1
4and r(x) = −74
We defineA/BandA%Bto be the quotient and remainder, respectively, when wedivide a(x) by b(x)
To this end, we define the procedurequot_rem(A,B,Q,R)(see lines 300–321)
to find the quotient and remainder Theoperator/andoperator%make use of
quot_remto do their work
Please note that the division methods require that K be a field If K is only acommutative ring (e.g.,longintegers), then most of the class template works fine,but the division methods do not
Trang 1112.3.7 Output to the screen
The operator<<for writing to the computer’s screen appears on lines 269–289.This operator writes the polynomial 5x3− x +1
2 like this:
(5)Xˆ3 + (-1)X + (0.5)
The procedure is smart enough to omit terms whose coefficient is zero, to omit thesuperscript 1 on the linear term, and to omit the variable altogether on the constantterm However, it does not convert(-1)Xinto the more legible- X, or even- (1)X
We might think that it is possible for the code to check if a coefficient is negative andmodify behavior accordingly However, for some fields K (such as C and Zp) thisdoes not make sense
12.3.8 GCD
Let a(x) and b(x) be polynomials A common divisor of a(x) and b(x) is a nomial c(x) with the property that there exist polynomials s(x) and t(x) so thata(x) = c(x)s(x) and b(x) = c(x)t(x) A greatest common divisor of a(x) and b(x)
poly-is a common divpoly-isor of highest possible degree
Two polynomials may have several different greatest common divisors becauseany nonzero scalar multiple of a greatest common divisor is again a greatest commondivisor
To settle on a specific meaning for gcd[a(x), b(x)] we choose the greatest commondivisor d(x) whose leading coefficient is 1 (A polynomial whose leading coefficient
is 1 is called monic.) Any two nonzero polynomials have a unique monic greatestcommon divisor
Thegcdprocedure for two polynomials is given on lines 323–336 This dure uses the helper methodsis_monic()andmake_monic(); the former checks
proce-if the polynomial is monic and the latter transforms the polynomial into a monicpolynomial by dividing by the leading coefficient See lines 256–265
We use the Euclidean algorithm (described in Section 3.3) to calculate the gcd oftwo polynomials
In addition to the usual gcd procedure, we provide an extended version Givenpolynomials a(x) and b(x), the extended gcd procedure finds d(x) = gcd[a(x), b(x)]
as well as polynomials s(x) and t(x) so that d(x) = a(x)s(x) + b(x)t(x) See lines337–376
Trang 1395 for (long k=0; k<=dg+n; k++) coef[k] = coef[k-n];
96 for (long k=dg+n+1; k<=dg; k++) coef[k] = K(0);
102 for (long k=dg; k>=0; k ) coef[k+n] = coef[k];
103 for (long k=0; k<n; k++) coef[k] = K(0);
Trang 14139 bool operator==(const Polynomial<K>& that) const {
140 if (dg != that.dg) return false;
147 bool operator!=(const Polynomial<K>& that) const {
148 return !(*this == that);
157 for (long k=0; k<=dmax; k++) {
158 ans.coef[k] = get(k) + that.get(k);
164 Polynomial<K> operator+=(const Polynomial<K>& that) {
165 (*this) = (*this) + that;
Trang 15181 for (long k=0; k<=dmax; k++) {
182 ans.coef[k] = get(k) - that.get(k);
188 Polynomial<K> operator-=(const Polynomial<K>& that) {
189 (*this) = (*this) - that;
195 if (isZero() || that.isZero()) return ans;
196 long dans = dg + that.dg;
209 Polynomial<K> operator*=(const Polynomial<K>& that) {
210 *this = (*this) * that;
Trang 16251 Polynomial<K> operator%=(const Polynomial<K>& that) {
252 (*this) = (*this) % that;
Trang 17291 template <class J, class K>
292 Polynomial<K> operator+(J x, const Polynomial<K>& P)
293 { return P + K(x); }
294
295 template <class J, class K>
296 Polynomial<K> operator-(J x, const Polynomial<K>& P)
297 { return (-P) + K(x); }
298
299 template <class J, class K>
300 Polynomial<K> operator*(J x, const Polynomial<K>& P)
Trang 18347 // If A and B are both 0, set S=T=0 and return 0.
348 if (A.isZero() && B.isZero()) {
In Chapter 3 we considered the question (phrased imprecisely here): What is theprobability that two positive integers are relatively prime? We found that the answer
is 1/ζ (2) Here we consider a similar problem: What is the probability that two
Trang 19randomly chosen polynomials are relatively prime?
To be more precise, let Bd denote the set of all polynomials in Z2[x] of degreeless than d; there are 2d such polynomials ad−1xd−1+ ad−2xd−2+ · · · + a1x+ a0where the ajs are 0 or 1 Let pddenote the probability the two polynomials, chosenuniformly and independently from Bdare relatively prime What can we say about
pdas d → ∞?
To formulate a conjecture, we write a program to evaluate pdby direct tion This is the approach we used in Section 3.5 With luck, modest values of d willlead us to the answer The overall structure of the program is this:
enumera-1 Ask the user to input d
2 Build an array containing all the polynomials in Bd
3 For all i < j, count the number of times the ith and jth polynomials are tively prime
rela-4 From this count, we learn the numerator of pd Divide by 22d to find theanswer
Of these, the most difficult part is the construction of the list in step 2 To generatethis table efficiently, we observe that there is a natural one-to-one correspondencebetween d-digit binary numbers and polynomials in Bd, illustrated here with d = 6
bd−1bd−2 b1b0 7→ bd−1xd−1+ bd−2xd−2+ · · · + b1x+ b0∈ Bd
We call this procedurelong2poly Here is its header file
Program 12.5: Header file long2poly.h
1 #ifndef LONG_TO_POLY_H
2 #define LONG_TO_POLY_H
3
Trang 20This header defines a constantmax_bitsthat sets an upper bound on d; this value
is based on the size of alonginteger on the computer on which this program is to
be run
The procedure takes alonginteger argument and returns aPolynomial<Mod>
To write this program, we want to access the individual bits of the integer argument,
m The way we do this is to check ifmis even or odd, and then set b0accordingly Wethen dividemby 2, check if the result is even or odd, and then set d1 We continue inthis fashion untilmis zero Here is the code
Program 12.6: Code file for the long2poly procedure
Next, we need a main to implement the exhaustive algorithm
Program 12.7: Main program for the GCD revisited problem
Trang 2123 cerr << "Generating polynomials ";
24 for (long k=0; k<bound; k++) {
25 list[k] = long2poly(k);
26 }
27 cerr << "done! " << endl << bound
28 << " polynomials of degree less than "
34 for (long i=0; i<bound-1; i++) {
35 for (long j=i+1; j<bound; j++) {
36 if( gcd(list[i],list[j]) == one ) count++;
42 cout << count << " out of " << bound*bound
43 << " pairs are relatively prime" << endl;
Enter degree bound > 10
Generating polynomials done!
1024 polynomials of degree less than 10 generated
524289 out of 1048576 pairs are relatively prime
Trang 2212.5 Working in binary
Thelong2polyprocedure used a trick to convert alonginteger m into mials p(x) in Z2[x] We set the constant coefficient of p(x) based on the parity of m,and then we divided m by 2 (keeping only the integer part) We then repeated thistechnique to set higher and higher coefficients until m vanished In short, we useddivision arithmetic to read off the base-2 digits of m
polyno-In other words, we used a mathematical trick to find the binary representation of
m However, the binary is already present inside the computer; it is more efficient towork directly with that C++ provides a family of operators for working directly onthe bits in the binary form of integers
12.5.1 Signed versus unsigned integers
Integers are stored inside the computer in binary The number 20 is representedinternally as0000000000010100
In this, and subsequent examples, we assume the integers are held asshorttypes;
on my computer these are two bytes (16 bits) long Other integer types may have 32
rep-to the type name For example:
unsigned short x;
To illustrate the difference, suppose we have two variablesxandydeclared thus:unsigned short x;
short y;
Suppose both of these hold the bits1111111111111111 In this case, the value of
xis 65,535 (216− 1) whereas the value ofyis −1
Trang 2312.5.2 Bit operations
C++ provides six operators for working with the binary representation of integers.Bitwise and For integer variablesxandy, the expressionx&yis the bitwise and of
xandy That is, the kth bit ofx&yis 1 if and only if the kth bits of bothxand
yare 1 Here is an example
x 0100001101100000
y 0001000111101101x&y 0000000101100000
The bitwise and operation & should not be confused with the Boolean andoperation&& You should use&&only withboolvalues
Bitwise or Similar to bitwise and, the operationx|ygives the bitwise or ofxandy.That is, the kth bit ofx|yis 0 if and only if the kth bits of bothxandyare 0.Here is an example
x 0100001101100000
y 0001000111101101x|y 0101001111101101
The bitwise or operation|should not be confused with the Boolean or tion|| You should use||only withboolvalues
opera-Exclusive or The expressionxˆygives the bitwise exclusive or ofxandy That is,the kth bit ofx|yis 0 if and only if exactly one of the kth bits of bothxandy
is 1 Here is an example
x 0100001101100000
y 0001000111101101xˆy 0101001010001101
Bitwise not The expression˜xinterchanges 1s and 0s inx That is, the kth bit of
˜xis 1 if and only if the kth bit ofxis 0 Here is an example
x 0100001101100000
˜x 1011110010011111
The bitwise not operation˜should not be confused with the Boolean not eration! You should use!only withboolvalues
op-Left shift The expressionx<<n(where n is a nonnegative integer) shifts the bits of
xto the left n steps The right-hand side of the result is filled with 0s Any bits
in the highest n positions are lost Here is an example
x 0100001101100000
Trang 24The symbol <<is the same one we use for writing to the console, as in thestatementcout << x << endl; C++ is able to distinguish between thesecases by inspecting the types of objects on either side of the<<symbol.The expressionx<<nis equivalent to multiplying x by 2n(unless bits are lost
at the left)
Right shift The expressionx>>n(where n is a nonnegative integer) shifts the bits
of x to the right n places Bits in the lower n places are lost The vacatedpositions on the left are filled in with 0s or with 1s depending on the situation:
• Ifxis anunsignedinteger type, 0s are inserted at the left
• Ifxis a signed integer type andxis nonnegative, 0s are inserted at theleft
• Ifxis a negative integer, then 1s are inserted at the left Here are someexamples
All six of these operators can be combined with the assignment operator,= Theexpressionx &= yis equivalent tox = (x&y), and so on
Bit operations can be combined to perform operations that would be difficult withstandard mathematical operators For example, suppose we want to set the kth bit of
xto 1; the following code does the trick:x |= (1<<k); If we want to set that bit
to zero, we do this:x &= ˜(1<<k);
12.5.3 Thebitsetclass template
Using integer types to represent a list of binary values is efficient, but presents twodrawbacks First, this technique is limited to the size of an integer on your computer;
if you want a list of, say, 200 bits, there is no integer type with that capacity Second,using bit manipulation can result in obfuscated code Human beings find statementssuch asx&=˜(1<<k);difficult to understand (The statement sets the kth bit ofxtozero.) If your problem requires high speed for short lists of bits, then bit manipulation
of integer types may be your best option However, there are two other choices ofwhich you should be aware
The first option, also discussed in Section 8.4, is to use vector<bool>ables; these are adjustable arrays of true/false values To set the kth bit of such an
Trang 25vari-array equal to zero (false), we use the considerably clearer statement x[k]=0;
or x[k]=false; Variables of typevector<bool>use memory efficiently, can
be easily resized, and provide convenient access to their elements However, thebitwise operations (such as&, ˜, >>, etc.) cannot be used with variables of type
vector<bool> If one wished to interchange all the 0s and 1s held inx, the mentx=˜x;does not work Instead, one would need to write aforloop to changethe bits one by one:
state-for (int k=0; k<x.size(); k++) {
x[k] = !x[k];
}
The second option is to use abitset Abitsetobject is a fixed size tory of bits To use variables of typebitset, start with#include <bitset>anddeclare variables like this:
reposi-bitset<100> x;
This sets upxas a list of 100 bits Notice thatbitsetis a template but its argument
is a number, not a type; we explain how to do this later in this section The importantpoint is that this number is a constant, not a variable The following code is illegal.int n;
cout << "Enter number of bits > ";
cin >> n;
bitset<n> x; // illegal constructor, n is not a constant
The size of thebitsetmust be declared when you write your program, not whilethe program is running
Here is a list of the various methods and operators available forbitsets
• Constructors The standard constructor has the form
bitset<number> var;
wherenumberis a specific positive integer This may be aconst intdefinedearlier in the code, or an explicitly typed value, such as 100 The variablevar
holdsnumberbits, and at this point these are all 0s
One may construct from anunsigned longinteger value For example,bitset<20> x(39);
setsxto00000000000000100111(the binary representation of 39).One may also construct from a C++stringobject (these are discussed later
in Section 14.2) The constructor
Trang 26bitset<20> y(x);
makesya copy ofx Note thatxmust also be abitset<20>and may not be
abitsetof any other size
• Inspection methods These are methods one can use to learn informationabout the bits held in abitset Supposexis abitset<100>:
– x.size()returns the number of bits thatxholds (in this example, 100).– x.any()returnstrueif at least one bit inxis a 1
– x.none()returnstrueif all of the bits are 0
– x.count()returns the number of 1s inx
– x.test(k)returnstrueif the kth bit ofxis a 1 Of course,kmust be
at least 0 and less thanx.size()
• Bit manipulation methods The following methods may be used to alter thevalue held in the bits of abitset Supposexis abitset<100>:
– x.set()sets all ofx’s bits to 1
– x.set(k)sets the kth bit to 1
– x.set(k,b)sets the kth bit base on the value held in the integer variable
b Ifbis zero, the kth bit ofxis set to 0; otherwise it is set to 1
– x.reset()sets all ofx’s bits to 0
– x.reset(k)sets bit k to 0
– x.flip()swaps 0 and 1 values in every position ofx For example,supposexholds 1110001110; after the statementx.flip();, it nowholds0001110001
– x.flip(k)flips the kth bit ofx
• Comparison operators Ifxandyare bothbitsets of the same size, then
we may compare them with the usual expressionsx==yandx!=y
• Bit operators The standard bitwise operators (&,|,ˆ,˜,<<,>>) and theirassignment variants (&=, |=, ˆ=, ˜=, <<=, >>=) may be used on a pair of
bitsets of the same size
• Array style access In addition to the methods described above, individualelements of abitsetmay be accessed using square brackets The expression
x[k]is the kth element ofx The expressionx[k]may appear on the right orthe left of an assignment statement such asx[4]=˜x[10];
In addition, the expressionx[5].flip()is equivalent tox.flip(5); both
of these toggle the fifth bit ofx