Express Binary Numbers in C++
C++ variables are stored internally as so-called binary numbers. Binary numbers are stored as a sequence of 1 and 0 values known as bits. Most of the time, you don’t really need to deal with which particular bits you use to represent numbers. Sometimes, however, it’s practical and convenient to tinker with numbers at the bit level — so C++ provides a set of operators for that purpose.
The so-called bitwise logical operators operate on their arguments at the bit level. To understand how they work, first examine how computers store variables.
The decimal number system
The numbers you’ve been familiar with from the time you could first count on your fingers are known as decimal numbers because they’re based on the number 10. In general, the programmer expresses C++ variables as decimal numbers. Thus you could specify the value of var as (say) 123, but consider the implications.
A number such as 123 refers to 1 * 100 + 2 * 10 + 3 * 1. All of these base numbers — 100, 10, and 1 — are powers of 10.
123 = 1 * 100 + 2 * 10 + 3 * 1
Expressed in a slightly different (but equivalent) way, 123 looks like this:
123 = 1 * 102 + 2 * 101 + 3 * 100
Remember that any number to the zero power is 1.
Other number systems
Well, okay, using 10 as the basis (or base) of our counting system probably stems from those 10 human fingers, the original counting tools. An alternative base for a counting system could just as easily have been 20.
If our numbering scheme had been invented by dogs, it might well be based on 8 (one digit of each paw is out of sight on the back part of the leg). Mathematically, such an octal system would have worked just as well:
12310 = 1 * 82 + 7 * 81 + 3 * 80 = 1738
The small 10 and 8 here refer to the numbering system, 10 for decimal (base 10) and 8 for octal (base 8). A counting system may use any positive base.
The binary number system
Computers have essentially two fingers. Computers prefer counting using base 2. The number 12310 would be expressed this way:
12310 = 0*27 + 1*26 + 1*25 + 1*24 + 1*23 + 0*22 + 1*21 + 1*20 12310 = 0*128 + 1*64 + 1*32 + 1*16 + 1*8 + 0*4 + 1*2 + 1*1 = 011110112
Computer convention expresses binary numbers by using 4, 8, 16, 32, or even 64 binary digits, even if the leading digits are 0. This is also because of the way computers are built internally.
Because the term digit refers to a multiple of 10, a binary digit is called a bit (an abbreviation of binary digit). A byte is made up of 8 bits. (Calling a binary digit a byte-it didn’t seem like a good idea.) Memory is usually measured in bytes (like rolls are measured in units of baker’s dozen).
With such a small base, you have to use a large number of bits to express numbers. Human beings don’t want the hassle of using an expression such as 011110112 to express such a mundane value as 12310. Programmers prefer to express numbers by using an even number of bits.
The octal system — which is based on 3 bits — was the default binary system in the early days of C. We see a vestige of this even today — a constant that begins with a 0 is assumed to be octal in C++. Thus, the line:
cout << "0173 = " << 0173 << endl;
produces the following output:
0173 = 123
However, octal has been almost completely replaced by the hexadecimal system, which is based on 4-bit digits.
Hexadecimal uses the same digits for the numbers 0 through 9. For the digits between 9 and 16, hexadecimal uses the first six letters of the alphabet: A for 10, B for 11, and so on. Thus, 12310 becomes 7B16, like this:
123 = 7 * 161 + B (i.e. 11) * 160 = 7B16
Programmers prefer to express hexadecimal numbers in multiples of 4 hexadecimal digits even when the leading digit in each case is 0.
Finally, who wants to express a hexadecimal number such as 7B16 by using a subscript? Terminals don’t even support subscripts. Even on a word processor, it’s a drag to change fonts to and from subscript mode just to type two lousy digits.
Therefore, programmers (no fools, they) use the convention of beginning a hexadecimal number with a 0x. Thus, 7B becomes 0x7B. Using this convention, the hexadecimal number 0x7B is equal to 123 decimal while 0x123 hexadecimal is equal to 291 decimal. The code snippet
cout << "0x7B = " << 0x7B << endl; cout << "0x123 = " << 0x123 << endl;
produces the following output:
0x7B = 123 0x123 = 291
You can use all the mathematical operators on hexadecimal numbers in the same way you’d apply them to decimal numbers.
If you really want to, you can write binary numbers in C++ ’14 using the prefix ‘0b’. Thus, 123 becomes 0b01111011.