Lecture 2: Numerical representation (by Trek Palmer) ------------- We're all used to using a base-positional number system, but what does it actually mean? We commonly use a base-10 system (decimal) and we're used to dealing with powers of 10 all the time. Consider the number 1024. What does the string "1024" actually denote? It really represents a weighted sum of the individual digits, where the location of a digit in the string indicates the value by which it should be weighted. So, 1024 actually means 1*1000 + 0*100 + 2*10 + 4*1, or using power notation: 1024 = 1*10^3 + 0*10^2 + 2*10^1 + 1*10^0. As good computer scientists, you may have noticed that the powers resemble indices in an array, and that's not far from the truth. A base positional number is an array (mathematicians like to use the word sequence) of digits, where the index of the digit indicates the power of the base to multiply the digit by. Now, it can be a little weird because we normally draw arrays as growing from left to right and our number indices grow from right to left. Binary ============ We're all taught to use base 10, so we're comfortable with decimal numbers. Computers, however, use a different base. Although some early machines (like UNIVAC) had components with decimal state, due to technological reasons modern computers all use base 2. This is commonly referred to as binary. Because each position corresponds to a power of two, the only valid digits in binary are 0 and 1 (please make sure that you understand why). So, because 2^0 is one, the binary numbers 0 and 1 have the same meaning as in decimal. But, what does 10 (in binary) mean? To find out, we just calculate the weighted sum. 10 = 1*2^1 + 0*2^0 = 2. So 10 in binary is equivalent to 2 in decimal. What value does 101010 represent? 1*2^5 + 0*2^4 + 1*2^3 + 0*2^2 + 1*2^1 + 0*2^0 = 32 + 8 + 2 = 42 What value does 10001111 represent? 1*2^7 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0 = 128 + 8 + 4 + 2 + 1 = 128 + 15 = 143 MSB and LSB =========== The most significant bit (otherwise known as the high order bit) is the bit with the highest place value. The least significant bit (aka low-order bit), is the bit with the lowest place value. Some useful hints and tricks for binary: ======================================== - A string of all ones is one less than the next highest power of 2. (e.g. 1111 = 2^4 - 1 = 15) - You can tell whether or not a binary number is odd by just inspecting the lowest bit. (e.g. 3 = 11 is odd, 5 = 101 is odd, but 6 = 110 is not) Try and understand why this is. - Memorize the first 10 or so powers of two, they do come in handy: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 ----+-----+----+----+----+----+----+-----+-----+-----+------ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 Inside a computer, all information is conveyed as a series of bits. When people talk about a "32-bit" architecture, what they mean is that, internally, the processor is capable of dealing with 32-bit values. The registers are (at least) 32 bits wide, the processor is capable of pushing 32-bits of information around between the functional units, and communication to and from memory can be in 32-bit chunks. What's the largest (integer) value a 32-bit machine can store in one of its registers? 32 ones, which is 2^32 - 1, or roughly 4 billion. Octal (base-8) =============== Octal is another representational scheme. It is less popular than it once was, but it still pops up and crusty old IBM programmers can be particularly fond of it. So, octal is base-8, which means that there are only 8 valid digits. So, for convenience's sake, we use the decimal digits 0-7. Often, to distinguish octal values from binary and decimal values, an octal number is prefixed with an extraneous 0. What value does 0100 (octal) represent? 1*8^2 + 0*8^1 + 0*8^0 = 64. What value does 01077 represent? 1*8^3 + 0*8^2 + 7*8^1 + 7*8^0 = 512 + 56 + 7 = 575 By and large, octal is really only used for explicitly encoding ASCII characters in strings in Algol-like languages (such as C or Java). Hexadecimal (base-16) ===================== Hexadecimal is a further representational scheme. It is quite popular because it only takes 8 hexadecimal digits to represent a 32-bit value (such as an IP address). Hexadecimal is base-16, and because it is a base that is capable of using more digits than decimal, we encounter a problem we didn't have with binary or octal. How do you represent the value ten? In decimal 10 means 1*10^1, but in hexadecimal 10 = 1*16^1! So we need to do something so we can write the values from ten to fifteen. The solution in common use is to use letters from the Latin alphabet. So: A=10, B=11, C=12, D=13, E=14, F=15. Another convention is that to distinguish hexadecimal numbers from decimal numbers, we prefix the string "0x" to any hex value. So, 10 = ten, but 0x10 = sixteen. What value does 0x1001 represent? 1*16^3 + 0*16^2 + 0*16^1 + 1*16^0 = 4096 + 1 = 4097 What value does 0xffff represent? 15*16^3 + 15*16^4 + 15*16^1 + 15*16^0 = 65535 Some useful tricks for hex ========================== - You don't really have to memorize the powers of sixteen. Just remember that 16 = 2^4 and that (x^y)^z = x^(y*z) - To convert between hex and binary, remember that: - Every hex digit becomes exactly 4 binary digits, and - Every four binary digits become exactly one hex digit Conversion between bases ========================= Converting numbers between bases is essentially a sort of long division. Like long division, you first find the largest power of the base that is still less than the number, scale that by a value and then subtract the product from the number to be converted. Some motivating examples: Decimal -> Binary Decimal: 155 2^7 = 128 < 155, 2^8 = 256 > 155, so we pick 128 now we find out what's left over (and still needs to be converted) 155 - 128 = 27 2^4 = 16 < 27, 2^5 = 32 > 27, pick 16 27 - 16 = 11 2^3 = 8 < 11, 16 > 11, pick 8 11 - 8 = 3 2^2 = 4 > 3, 2 < 3, pick 2 3 - 2 = 1, pick 1 So the resulting value is 128 + 16 + 8 + 2 + 1, in binary: 10011011 Decimal -> Hexadecimal Decimal: 155 16^1 = 16 < 155, 16^2 = 256 > 155, pick 16 Now, because we have a choice of digits, we need to decide how much to scale 16 in order to reduce 155 as much as possible. 16*9 = 144 < 155, 16*10 = 160 > 155, pick 9 155 - 144 = 11 16^1 > 11, 16^0 = 1 < 11, pick 1 we now need to scale 1 by 0xB (11) So the resulting value is: 9*16 + 11*1 = 0x9B we can check this by converting it to binary and comparing it with the value above: 0x9B = 1001 1011 (using the 4-digits trick). And the values match. Binary Addition ================ Now that you know how to represent (integral) binary values, you might as well learn how to add them. Fortunately, with binary there are only a limited number of possible combinations. 0 0 1 1 + 0 + 1 + 0 + 1 ---- ---- ---- ---- 0 1 1 10 Simple enough. Only the last case is unusual. But, all that happens is you carry the one over to the two's place. Basically, all you need to do is dust off your old elementary-school addition skills and remember how to carry. Ex. carries: 11111 11 101011 1000011 + 11110 + 110110 --------- ---------- 1001001 1111001 Hex Addition ============ Adding hex numbers is more or less the same, but in reality people either convert them to decimal to add them, or convert them to binary to add them. Binary Subtraction ================== Subtracting binary numbers is similar to addition, you just need to borrow rather than carry. Remember your elementary arithmetic! Ex. borrows: 11 1 1111 110010 100000 - 11001 - 11101 --------- --------- 11001 11 As you can see, binary subtraction can be more challenging than binary addition. There's also the issue of negative numbers to deal with.