Three notations for an integer:
Binary (base 2)
Decimal (base 10)
Hexadecimal (base 16)

The digits of an integer (2025) written in decimal (base 10)

In decimal, each place has 10 times the value of the previous one.
Depending on the number, we might need ten decimal digits to write it: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

1000’s
place
100’s
place
10’s
place
1’s
place
2 0 2 5




2 × 1000 = 2000
0 ×  100 =    0
2 ×   10 =   20
5 ×    1 =    5
           2025

The digits of the same integer (2025), written in binary (base 2)

In binary, each place has 2 times the value of the previous one.
The only binary digits we will ever need to write are 0 and 1.

A binary digit (either 0 or 1) is called a bit.
Today we write the two possible values of a bit as 0 or 1.
In the days of Morse Code, we wrote them as “dot” and “dash”.

A series of 8 bits is called a byte. For example, 01010111.
A series of 4 bits is called a nibble. For example, 0101.

1024’s
place
512’s
place
256’s
place
128’s
place
64’s
place
32’s
place
16’s
place
8’s
place
4’s
place
2’s
place
1’s
place
1 1 1 1 1 1 0 1 0 0 1




1 × 1024 = 1024
1 ×  512 =  512
1 ×  256 =  256
1 ×  128 =  128
1 ×   64 =   64
1 ×   32 =   32
0 ×   16 =    0
1 ×    8 =    8
0 ×    4 =    0
0 ×    2 =    0
1 ×    1 =    1
           2025

Some examples of integers written in binary

On our machine storm.cis.fordham.edu, an int occupies 32 bits.

00000000000000000000000000000000  (zero)
00000000000000000000000000000001  (one)
00000000000000000000000000000010  (two)
00000000000000000000000000000011  (three)
00000000000000000000000000000100  (four)
00000000000000000000000000000101  (five)
00000000000000000000000000000110  (six)
00000000000000000000000000000111  (seven)
00000000000000000000000000001000  (eight)
00000000000000000000000000001001  (nine)
00000000000000000000000000001010  (ten)
00000000000000000000000000001011  (eleven)
00000000000000000000000000001100  (twelve)
00000000000000000000000000001101  (thirteen)
00000000000000000000000000001110  (fourteen)
00000000000000000000000000001111  (fifteen)
00000000000000000000000000010000  (sixteen)
00000000000000000000000000010001  (seventeen)
00000000000000000000011111101001  (two thousand twenty-five)

Hexadecimal (base 16) notation

We wrote the number 2025 with only four digits in decimal,
            2025
but we needed 11 digits to write it in binary:
     11111101001
We usually consider bits in groups of 4 or 8 at a time, so let’s add five leading 0s to make 16 bits:
0000011111101001

Binary numbers usually need many more digits than decimal. That’s why they invented hexadecimal digits. Each hexadecimal digit (hex digit) is an abbreviation for a series of four bits (one nibble). There are 16 possible hexadecimal digits:

hex
digit
nibble
(4 bits)
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111

We can now write out 16-bit number (2025 = 0000011111101001) with only 4 hex digits (07E9).
When you write a hexadecimal number in a C++ program, you must write a 0x in front of it: 0x07E9.

  32768’s
place
16384’s
place
8192’s
place
4096’s
place
2048’s
place
1024’s
place
512’s
place
256’s
place
128’s
place
64’s
place
32’s
place
16’s
place
8’s
place
4’s
place
2’s
place
1’s
place
binary 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1
hex 0 7 E 9





Exercise. Write the following 32-bit integer as 8 hexadecimal digits. Do they spell anything? I put in spaces betwene the bytes to make it easier to read. (This example from The Practice of Programming (1999) by Brian W. Kernighan and Rob Pike, p. 159.)
11011110 10101101 10111110 11101111

Write HTML colors in hexadecimal

An HTML rgb (red/green/blue) color code in a web page can be written as three two-digit hexadecimal numbers, instead of three eight-bit binary numbers.

red FF 00 00 11111111 00000000 00000000
orange FF 80 00 (a mixture of red and some green) 11111111 10000000 00000000
yellow FF FF 00 (a mixture of red and lots of green) 11111111 11111111 00000000
green 00 FF 00 00000000 11111111 00000000
blue 00 00 FF 00000000 00000000 11111111
black 00 00 00 00000000 00000000 00000000
while FF FF FF FFFFFFFF FFFFFFFF FFFFFFFF

For example, if you paste the following into a web page:

<SPAN STYLE = "color: #FF0000;">Hello.</SPAN>
<BR/>
<SPAN STYLE = "background-color: #FF0000;">Hello.</SPAN>

you will see

Hello.
Hello.

Outputting an integer in hexadecimal is easy.

hex.C, hex.txt: uses a series of four i/o manipulators.

Outputting an integer in binary is harder.

bitset.C, bitset.txt: uses machinery I can’t explain yet.

To learn how to output an integer in binary tonight, we will need two of the following “bitwise” operators:

<< left shift
>> right shift
& bitwise and
| bitwise or

Left-shift through all the places of an int

In the decimal world, left-shifting a number multiplies it by 10. For example,

   7     (seven)
  70     (seventy)
 700     (seven hundred)
7000     (seven thousand)

In the binary world, left-shifting a number multiplies it by 2. For example,

   111   (seven)
  1110   (fourteen)
 11100   (twenty-eight) 
111000   (fifty-six)
	//The "left shift" operator <<
	//Its left operand is always an integer (in this case, n).

	int n {0x7};    //In binary, n is 00000000 00000000 00000000 00000111
	int i {n << 1}; //In binary, i is 00000000 00000000 00000000 00001110
	int j {n << 2}; //In binary, j is 00000000 00000000 00000000 00011100
	int k {n << 3}; //In binary, k is 00000000 00000000 00000000 00111000

left.C, left.txt,
demonstrates that each place in a binary number has twice the value of the previous place.

The C++ operator << is overloaded. That means it can do two different things, depending on the data type of its operands:

  1. If the left operand of << is a destination for output (such as the familiar cout or cerr), the << will perform output.
    	cout << "hello\n";
    
  2. If the left operand of << is an int (such as the 1 in left.C, or the following i), the << will perform left-shift.
    	int i {1};
    	i << 3;
    

There’s right-shift, too

right.C, right.txt.

	//The "right shift" operator >>
	//Its left operand is always an integer (in this case, n).

	int n {0xE};    //In binary, n is 00000000 00000000 00000000 00001110
	int i {n >> 1}; //In binary, i is 00000000 00000000 00000000 00000111
	int j {n >> 2}; //In binary, j is 00000000 00000000 00000000 00000011
	int k {n >> 3}; //In binary, k is 00000000 00000000 00000000 00000001
	//The "input" operator >>
	//Its left operand is always a source of input (in this case, cin).

	int n {0};
	cin >> n;

Use “bitwise and” to turn off selected bits

The “bitwise and” operation is simpler than addition or subtraction, because there is no carrying or borrowing. In the following example, the mask 0011 gives us a result in which only the two rightmost bits of the original number (the 1010 in the top line) survive unchanged. The other bits of the original number get zeroed out.

  1010   the original number
& 0011   Allow only the 2 rightmost bits of the original number to survive unchanged.
  0010   The rest of the bits in the result are all 0s.
	//The "bitwise and" operator &

	int n {0xA};    //In binary, n is 00000000 00000000 00000000 00001010
	int m {0x3};    //In binary, m is 00000000 00000000 00000000 00000011
	int j {n & m};  //In binary, j is 00000000 00000000 00000000 00000010

Use “bitwise and” to turn off one bit of a byte

  01100001   the original number (the ASCII code for lowercase 'a')
& 11011111   Allow 7 of the 8 bits of the original number to survive unchanged.
  01000001   Bit 5 has been changed to 0.

toupper.C, toupper.txt.

Use “bitwise or” to turn on selected bits

The “bitwise or” operation is simpler than addition or subtraction, because there is no carrying or borrowing. In the following example, the mask 0011 gives us a result in which only the two leftmost bits of the original number (the 1010 in the top line) survive unchanged. The other bits of the original number get changed into ones.

  1010   the original number
| 0011   Allow only the 2 leftmost bits of the original number to survive unchanged.
  1011   The rest of the bits in the result are all 1s.
	//The "bitwise or" operator &

	int n {0xA};    //In binary, n is 00000000 00000000 00000000 00001010
	int m {0x3};    //In binary, m is 00000000 00000000 00000000 00000011
	int j {n | m};  //In binary, j is 00000000 00000000 00000000 00001011

Use “bitwise or” to turn on one bit of a byte

  01000001   the original number (the ASCII code for uppercase 'A')
| 00100000   Allow 7 of the 8 bits of the original number to survive unchanged.
  01100001   Bit 5 has been changed to 1.

tolower.C, tolower.txt.

Output an int in binary using the bitwise operators

decimaltobinary.C, decimaltobinary.txt.

The value of the int is already stored in binary in the computer’s memory. To get the value of each bit individually, we will use >> (right shift) and & (bitwise and).

binary.C outputs the 32 bits of an int one at a time, from left to right. During each iteration, we shift a different bit of the original number n to a position all the way on the right, and then use bitwise and to assasinate all the other bits. Only the bit all the way on the right survives to be output.

Convert binary to decimal

binarytodecimal.C, binarytodecimal.txt.

The variable it is an iterator that gives us access to each char in the string s from right to left. (In other words, it is a reverse iterator.) We get access to each char by applying the operator * to the iterator, in the same way that we will soon apply the operator * to a pointer.

There are many types of iterator. The functions rbegin and the heart-rending function rend give us exactly the kind of iterator we need to loop backwards through the string s.

A conversion program that comes with Linux

bc is the binary calculator; -l is its math library.
ibase is the input base; obase is the output base.

Convert decimal to hexadecimal:

bc -l
obase=16
2025
7E9
2026
7EA
control-d

Convert hexadecimal to decimal:

bc -l
ibase=16
7E9
2025
7EA
2026
control-d

Convert decimal to binary:

bc -l
obase=2
2025
11111101001
2026
11111101010
control-d

Convert binary to decimal:

bc -l
ibase=2
11111101001
2025
11111101001
2026
control-d