2.1-4
题目:有两个各存放在数组A和B中的n位二进制整数,考虑它们的相加问题。两个整数的和以二进制形式存放在具有(n+1)个元素的数组C中。请给出这个问题的形式化描述,并写出伪代码。
解答:
形式化描述如下:
首先,初始化数组C,使其n+1各元素的值都为0。接着,利用for循环用i同时从n到1反向遍历A、B数组,每遍历一步,作一个判断:若A[i]+B[i]>1,则C[i]=C[i]+1;反之,C[i+1]=A[i]+B[i]。最后,当i=0时,for循环结束,此时C数组中存储的即是所求的结果。
问题思考:
先假设整数的二进制数组中,高位在前,低位在后,所以得从后面往前面加——即从低位往高位的顺序加,即循环顺序应为从大到小(n到1)。主要注意的一个问题就是进位的处理,当低位A[i]+B[i]>1时,就会向高位推送一个进位1,那么对于下一次的相加就应该有:A[i-1]+B[i-1]+进位。
这里把进位描述为carry_flag,并将其初始化为0。
那么就有通用表达式:C[i+1]=(A[i]+B[i]+carry_flag)%2,
这里之所以对2取余,是因为二进制只有0,1(貌似这句话多余了) ;之所以是C[i+1],而不是C[i],是因为C[n+1](即整数的二进制表示的最低位)的值应该是 (A[n]+B[n])%2 的结果,依次类推就有了上面的那个通用表达式,记得每次加完之后都要更新carry_flag。
伪代码:
BINARY-ADD(A,B,C,n)
▷这里假设整数的二进制表示中,高位在前,低位在后
carry_flag ← 0
for j ← n to 1
do key ← A[j]+B[j]+carry_flag
C[j+1] ← key mod 2
if key > 1
carry_flag ← 1
else
carry_flag ← 0
C[0] ← carry_flag
实现代码:
C++:
#include <stdio.h>
void binary_add(int* a, int *b, int *c, int length){
int i = 0;
int carry_flag = 0;
for(i=length-1; i>=0; i--){
int tmp = a[i]+b[i]+carry_flag;
c[i+1] = tmp % 2;
if(tmp>1){
carry_flag = 1;
}else{
carry_flag = 0;
}
}
c[0]=carry_flag;
}
void main(){
int i = 0;
int length = 0;
int A[8] = {1,0,1,1,1,0,0,1}; //185的二进制形式,高位在前,低位在后
int B[8] = {1,1,0,0,1,0,1,1}; //203的二进制形式,高位在前,低位在后
int C[9] = {0};
length = sizeof(A)/sizeof(int);
binary_add(A,B,C,length);
for(i=0;i<=length;i++){
printf("%d,",C[i]);
}
}
JAVA:
public class Test{
int[] A = {1,0,1,1,1,0,0,1}; //185的二进制形式,高位在前,低位在后
int[] B = {1,1,0,0,1,0,1,1}; //203的二进制形式,高位在前,低位在后
int[] C = {0,0,0,0,0,0,0,0,0};
private void binary_add(int[] a, int[] b, int[] c, int length){
int carry_flag = 0;
for(int i=length-1; i>=0; i--){
int tmp = a[i]+b[i]+carry_flag;
c[i+1] = tmp % 2;
if(tmp>1){
carry_flag = 1;
}else{
carry_flag = 0;
}
}
c[0]=carry_flag;
}
public static void main(String[] args){
Test test = new Test();
test.binary_add(test.A, test.B, test.C, test.A.length);
for(int i=0; i<=test.A.length; i++){
System.out.print(test.C[i]+",");
}
}
}