YP.2.5 Operations on Bits—Part I: Arithmetic (双语)

from:

[1] Introduction to Computing System, from Bits and Gates to C and Beyond. Yale N. Patt and Sanjay J. Patel. McGraw-Hill Higher Education.(英)

[2] 计算系统基础_陈道蓄http://course.jingpinke.com/details?uuid=8a833999-2031c13b-0120-31c13bb1-012b

2.5 Operations on BitsPart I: Arithmetic

2.5.1 Addition and Subtraction

Arithmetic on 2's complement numbers is very much like the arithmetic on decimal numbers that you have been doing for a long time.

Addition still proceeds from right to left, one digit at a time. At each point, we generate a sum digit and a carry. Instead of generating a carry after 9 (since 9 is the largest decimal digit), we generate a carry after 1 (since 1 is the largest binary digit).

Example 2.3

Using our five-bit notation, what is 11 + 3?

The decimal value 11 is represented as 01011

The decimal value 3 is represented as 00011

The sum, which is the value 14, is 01110

Subtraction is simply addition, preceded by determining the negative of the number to be subtracted. That is, A - B is simply A + (-B).

Example 2.4

what is 14 - 9?

The decimal value 14 is represented as 01110

The decimal value 9 is represented as 01001

First we form the negative, that is, -9: 10111

Adding 14 to -9, we get . 01110

10111

which results in the value 5. 00101

Note again that the carry out is ignored.

Example 2.5

What happens when we add a number to itself (e.g.,x +x)?

Let's assume for this example eight-bit codes, which would allow us to represent integers from - 128 to 127. Consider a value for A, the integer 59, represented as 00111011. If we add 59 to itself, we get the code 01110110. Note that the bits have all shifted to the left by one position. Is that a curiosity, or will that happen all the time as long as the sumx +x is not too large to represent with the available number of this?

Using our positional notation, the number 59 is

0 • 26 + • 25 + 1 • 24 + 1 • 23 +• 22 +1 • 21 + 1 • 20

The sum 59 + 59 is 2 • 59, which, in our representation, is

2 • (0 • 26 +• 25 +1 •24 + 1 • 23 +• 22 +1 • 21 + 1 • 20)

But that is nothing more than

0 • 27 + • 26 + 1 • 25 + 1 • 24 +• 23 +1 • 22 + 1 • 21 + 0 • 20

which shifts each digit one position to the left. Thus, adding a number to itself (provided there are enough bits to represent the result) is equivalent to shifting the representation one bit position to the left.

2.5.2 Sign-Extension

It is often useful to represent a small number with fewer bits. For example, rather than represent the value 5 as 0000000000000101, there are times when it is useful to allocate only six bits to represent the value 5:000101. There is little confusion, since we are all used to adding leading zeros without affecting the value of a number. A check for $456.78 and a check for $0000456.78 are checks having the same value.

What about negative representations ? We obtained the negative representation from its positive counterpart by complementing the positive representation and adding 1. Thus, the representation for -5, given that 5 is represented as 000101, is 111011. If 5 is represented as 0000000000000101, then the representation for -5 is 1111111111111011. In the same way that leading 0s do not affect the value of a positive number, leading 1s do not affect the value of a negative number. 

In order to add representations of different lengths, it is first necessary to represent them with the same number of bits. For example, suppose we wish to add the number 13 to - 5 , where 13 is represented as 0000000000001101 and -5 is represented as 111011. If we do not represent the two values with the same number of bits, we have

0000000000001101

       + 111011

When we attempt to perform the addition, what shall we do with the missing bits in the representation for -5? If we take the absence of a bit to be a 0, then we are no longer adding -5 to 13. On the contrary, if we take the absence of bits to be 0s, we have changed the -5 to the number represented as 0000000000111011, that is +59. Not surprisingly, then, our result turns out to be the representation for 72.

However, if we understand that a six-bit -5 and a 16-bit -5 differ only in the number of meaningless leading 1s, then we first extend the value of -5 to 16 bits before we perform the addition. Thus, we have

  0000000000001101

  + 1111111111111011

                                          0000000000001000

and the result is +8, as we should expect.

The value of a positive number does not change if we extend the sign bit 0 as many bit positions to the left as desired. Similarly, the value of a negative number does not change by extending the sign bit 1 as many bit positions to the left as desired. Since in both cases, it is the sign bit that is extended, we refer to the operation asSign-EXTension, often abbreviated SEXT. Sign-extension is performed in order to be able to operate on bit patterns of different lengths. It does not affect the values of the numbers being represented.

2.5.3 Overflow

Up to now, we have always insisted that the sum of two integers be small enough to be represented by the available bits. What happens if such is not the case?

You are undoubtedly familiar with the odometer on the front dashboard of your automobile. It keeps track of how many miles your car has been driven—but only up to a point. In the old days, when the odometer registered 99992 and you drove it 100 miles, its new reading became 00092. A brand new car! The problem, as you know, is that the largest value the odometer could store was 99999, so the value 100092 showed up as 00092. The carryout of the ten-thousands digit was lost. (Of course, if you grew up in Boston, the carryout was not lost at all—it was in full display in the rusted chrome all over the car.)

We say the odometer overflowed.Representing 100092 as 00092 is unacceptable. As more and more cars lasted more than 100,000 miles, car makers felt the pressure to add a digit to the odometer. Today, practically all cars overflow at 1,000,000 miles, rather than 100,000 miles.

The odometer provides an example of unsigned arithmetic. The miles you add are always positive miles. The odometer reads 000129 and you drive 50 miles. The odometer now reads 000179. Overflow is a carry out of the leading digit.

In the case of signed arithmetic, or more particularly, 2's complement arithmetic, overflow is a little more subtle.

Let's return to our five-bit 2's complement data type, which allowed us to represent integers from -16 to +15. Suppose we wish to add +9 and +11. Our arithmetic takes the following form:

01001

01011

10100

Note that the sum is larger than +15, and therefore too large to represent with our 2's complement scheme. The fact that the number is too large means that the number is larger than 01111, the largest positive number we can represent with a five-bit 2's complement data type. Note that because our positive result was larger than +15, it generated a carry into the leading bit position. But this bit position is used to indicate the sign of a value. Thus detecting that the result is too large is an easy matter. Since we are adding two positive numbers, the result must be positive. Since the ALU has produced a negative result, something must be wrong. The thing that is wrong is that the sum of the two positive numbers is too large to be represented with the available bits. We say that the result has overflowedthe capacity of the representation. 

Suppose instead, we had started with negative numbers, for example, -12 and -6. In this case our arithmetic takes the following form:

10100

11010

01110

Here, too, the result has overflowed the capacity of the machine, since -12+ -6 equals -18, which is "more negative" than -16, the negative number with the largest allowable magnitude. The ALU obliges by producing a positive result. Again, this is easy to detect since the sum of two negative numbers cannot be positive.

Note that the sum of a negative number and a positive number never presents a problem. Why is that? See Exercise 2.25.

2.5 比特运算—第一部分:算术运算

2.5.1 加法和减法

    二进制补码的算术运算与十进制运算十分相似。

    加法运算依然是从右到左进行,每次一位。在每次运算后,产生一个和与一个进位,与以往在9之后产生一个进位不同,因为9是最大的十进制数,我们现在是在1的后面产生一个进位,因为1是最大的二进制数。

 

例 2.3 用我们的五位二进制位组合表示,11+3的值是多少?                

十进制数11可以表示为 01011

十进制数3可以表示为  00011

两数之和是            01110

它的值是 14。

    

通过将减数变为它的负数就可以很容易地将减法转换为加法。也就是说,A-B用A+(-B)来实现。

 

例题2.4 14-9等于多少?

十进制数14表示为:           01110

十进制数9表示为:            01001

首先构造9的负数,也就是-9:  10111

把14与-9相加,我们得到:     01110

                              10111

结果是                        00101

当然它的十进制值是5

再次注意进位被忽略了。

 

例题2.5 如果我们把一个数加上它的自身会怎样?(比如说,xx

让我们再次假设在这个例子中采用8位码字,这样我们就可以表示从-128到127的整数。考虑若x为整数59(二进制码为00111011),加上自身后,我们得到01110110。注意到所有的码字向左移动了1位。这是偶然呢,还是会发生在所有xx的和上呢(假设有足够的位数用来表示数字)?

采用位置计数法,59可以表示为:

59+59的和是,同样地可以表示为:

上式也就是

,即每位上的数字都向左移了一位。因此,一个数自加(假设有足够的位数来表示数字)等价于把该数字的二进制表示中每位上的数字向左移一位。

2.5.2 符号扩展

    我们经常会用比较少的位数来表示一个小的数。例如,我们常常只用六位(000101)而不是用十六位(0000000000000101)来表示5这个值。这一点不会引起混淆,因为我们都习惯于这样一个事实:在一个数前加零并不影响这个数的值。一张456.78元的支票和一张0000456.78元的支票价值是相同的。

那么负数呢?通过对其相应的正数取反加一,我们就得到了负数的表示。这样,若5的表示为000101,那么-5就表示为111011。若5表示为0000 0000 0000 0101,那么-5就会相应的表示为1111 1111 1111 1011。正如开头的0对正数的实际值没有影响一样,开头的1也不会对负数的实际值产生影响。

为了对两个具有不同长度的数值做加法,首先必须要做的就是将它们表示为相同的长度。比如说,假设我们要做13和-5的加法,其中13表示为0000 0000 0000 1101,-5表示为111011。如果我们没有将两个数表示成相同的长度,就有:

0000000000001101

       +           111011

--------------------------------

当我们尝试去做加法运算时,我们要如何去处理-5表示中那些缺失的位呢?如果我们将空位以0填充,那么我们做的就不再是-5和13的加法,相反地,我们已经把-5的表示变成了0000 0000 0011 1011,即59。这样,当我们得到结果72时也就不会感到惊讶了。

不过,如果我们能认识到6位的-5与16位的-5唯一的区别就在于开头的1的个数的话,我们就可以在做加法之前先将-5的值扩展为16位,这样,我们就得到:

0000000000001101

+ 1111111111111011

   ------------------------------

结果就是 0000000000001000

即是我们所期望的8。

如果我们用0来扩展一个正数的左端,它的值不会改变。与此类似,如果用1来扩展一个负数的左端,其值亦不会改变。在这两种情况中扩展的都是符号位,我们将这种运算称为符号扩展,简称SEXT符号扩展用于对不同长度的数值之间的运算,它并不会改变数值本身。

2.5.3 溢出

到现在为止,我们一直强调:两个整数的和总是足够小,可以用给定的位数来表示。但若不是这种情况又会怎样呢?

让我们回到5位补码数据类型,它使我们能表示从-16到+15的整数。假设我们想要用9加11,算术过程如下:

01001

01011

10100

计算结果为-12,为什么会出现错误?原因是9加11等于20,大于+15,即大于01111,而01111是我们用5位的补码数据类型能够表示的最大正数,因此20不能用5位的补码表示出来。此外,在二数相加时,产生了一个到第一位的进位,但是这个位置是被用来表示数值的正负的。因此,检测结果是否太大,就是一件很容易的事。由于我们加的是2个正数,结果应该是正的,ALU得出一个负数结果,表明计算出错。出错的原因就是2个正数的和太大,不能使用提供的位数来表示。我们称之为溢出,即计算结果超出了这种表示方法的容量。

相反的,我们计算两个负数的和。举个例子,-12加-6。这种情况我们的运算如下:

10100

11010

01110

这里的结果也出现溢出的情况,-12加-6等于-18,比最小的负数-16还要小。ALU得到一个正的结果。同样,既然两个负数的和不可能是正数,这也很容易监测。

而一个负数和一个正数的和永远不会出现溢出,为什么? 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值