Multiplying and Dividing by 2 in Binary is Bit-Shifting! -------------------------------------------------------- One important point is not made clearly in the number representation notes: in binary, multiplying and dividing by powers of 2 is the same as shifting the bit pattern to the left or right! (In the notes below, the ^ symbol will mean "raised to the power", e.g. 10^2 = 100 and 2^5 = 32. Consider base-10 and the value 123. If you multiply by a power of 10, you add zeros which is like shift the digits-pattern to the left. So 123*10^1 = 1230. 123*10^3 = 123000. Divide by a power of 10? Shift to the right. 123/10 = 123*10^(-1) = 12.3. 123/1000 = 123*10^(-3) = 0.123. For binary, you have a value x and need to multiply it by some power of 2, i.e. 2^E, then you shift the bit pattern of x to the left if E is positive, i.e. add E zero's. So if you have 5 decimal which is 101 binary, and you need to multiply it by 8=2^3, then the binary will just be 101000 binary, which is 32+8=40. (Yep, that's 8*5!) Turns out this property plays a big role in how floating point numbers are represented. (See below.) Note also: if you're doing integer division by 2, then this means you're just "dropping" the right-most (or least-sigificant) bit. So if we divide 11 decimal by 2, then we'd start with binary 1011, then drop the right-most bit to get 101 which is 5. One more note: What's it mean to be odd or even? In binary, if the right-most (least significant bit) is 1, it's odd number. If it's 0, it's even. Representing floating point numbers in binary: ---------------------------------------------- In Lab 3 Part 5, we asked you to show us how to show how the value 3.0 is represented in IEEE single precision format (32 bits). Here are a couple of more examples of this. If you wanted to think of doing this conversion as an algorithm, the steps would be: 1) Convert the decimal floating-point value to binary, including the fractional part. 2) Determine how much to shift this binary representation to get it in the form 1.xxxx. 3) The bit pattern after the 1. in 1.xxxx will be the mantissa. 4) The number of shifts you did in (2) is the exponent -- convert this to excess-127. 5) If the number is negative, make the sign bit 1. Otherwise it's zero. 6) Put it all together in this order: sign-bit, exponent, mantissa (without the hidden bit). Re-write this is hex if you want (as 4 bytes or 8 hex digits). (If you look at it in memory using a debugger, bytes may be reversed.) Example 1: -17.75 in decimal. ---------- Step 1: To convert to binary, think of this as 16 + 1 + 1/2 + 1/4. In other words, it's 1*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 1*2^0 + 1*2^(-1) + 1*2^(-2) = 10001.11 in binary Step 2: For the internal IEEE representation, we want something of the form 1.xxxx so we can "drop" the hidden bit. So if we shift left 4 bits, then 10001.11 binary becomes 1.000111 binary. In other words, 10001.11 = 1.000111 * 2^4 in exactly the same way that in decimal 123 = 1.23*10^2 Step 3: Our mantissa will be 000111 followed by a bunch of zeros. We need 23 total bits for the mantissa for our 32 bit number, so "a bunch" is really 17 here. Step 4: Our exponent is 4, and to get this in excess-127 notation we add 127 to 4 to get 131 and then write this in binary. 131 = 128 + 2 + 1 in decimal, so it's 10000011 in binary. (Note we have 8 bits for the exponent.) Step 5: The sign bit is 1 since it's a negative value. Step 6: The complete binary representation for all 32 bits is as follows. I'll put spaces between the parts. 1 10000011 00011100000000000000000 Let's write this again, but group the bits in groups of 4 so we can easily make them hex digits: 1100 0001 1000 1110 0000 0000 0000 0000 C1 8E 00 00 If you looked in Visual Studio, you'd see this as: 00 00 8E C1 Example 2: 6.32 in decimal. ---------- Step 1: To convert to binary, think of this as 4 + 2 + 1/4 + 1/16 + ... where the ... means there are some smaller fractional powers of two we'd have to figure out. To keep things simple, let's ignore those, so the value we're really going to do here is 6.3125. (More on this at the end.) In other words 6.3125 is really 1*2^2 + 1*2^1 + 0*2^0 + 0*2^(-1) + 1*2^(-2) + 0*2^(-3) + 1*2^(-4) 110.0101 in binary Step 2: To get this to the form 1.xxxx we shift the decimal place left two places, which gives us 1.100101 and an exponent of 2. Step 3: Our mantissa will be 100101 followed by enough zeros to fill out the mantissa. (NOTE: If we *really* were doing 6.32 and not 6.3125 then the lesser-significant bits in the mantissa would include some ones that are needed to add up to the value 6.32.) Step 4: Our exponent is 2, and to get this in excess-127 notation we add 127 to 2 to get 129 and then write this in binary. 129 = 128 + 1 in decimal, so it's 10000001 in binary. (Note we have 8 bits for the exponent.) Step 5: The sign bit is 0. Step 6: The complete binary representation for all 32 bits is as follows. I'll put spaces between the parts. 0 10000001 10010100000000000000000 Let's write this again, but group the bits in groups of 4 so we can easily make them hex digits: 0100 0000 1100 1010 0000 0000 0000 0000 40 CA 00 00 If you looked in Visual Studio, you'd see this as: 00 00 ca 40 NOTE: If you use Visual Studio to see the pattern for our original value, 6.32, we'd see this: 71 3d ca 40 See, there are some ones now in those lesser-significant bits -- which are on the left of this expression because our Intel x86 architecture is little-endian. These ones are the smaller fractional powers of 2 needed to get 0.32 exactly in binary.