这两天一直在自学离散数学,有一道题目,花了我3个小时终于做出来了。特拿出来和大家交流
//
做一个二进制乘法的程序,输入b(n),b(n-1),...,b(0),b'(m),b'(m-1),...,b'(0)
// 输出c
/*
二进制的乘法表只有两种1×1=10,1×0=0,0×0=0
其中1×1=10是要进位的
利用和十进制相似的乘法原理,做出二进制的乘法,看例子
111
× 11
----------
111
111
----------
10101
*/
#include < iostream >
#include < cstring >
using namespace std;
// 首先归纳总结:对于a(n+1位),b(m+1位)的二进制数字相乘的结果不会大于n+m+2位
// 因为a <= 2^(n+1)-1 < 2^(n+1), b <= 2^(n+1)-1 < 2^(n+1)
// 所以a*b < 2^(n+m+2) (这个数字是n+m+3位的)
// 因此,a*b的位数<=n+m+2
// 以下的程序是根据输入的两数的排列是
// a(n),a(n-1),...,a(0)和b(m),b(m-1),...,b(0)来计算的
// 所以结果是倒过来的
/* 具体算法是这样的
a(n),a(n-1)...a(0)
× b(m),b(m-1)...b(0)
------------------------------------------------------
(1) b(0)a(n), b(0)a(n-1),...., b(0)a(1), b(0)a(0)
(2) b(1)a(n), b(1)a(n-1), ... , b(1)a(1), b(1)a(0)
.
.
.
(m) b(m-1)a(n), b(m-1)a(n-1)
(m+1) b(m)a(n), b(m)a(n-1)
结果放在一个c(m+n)...c(0)的数组中,这个数组中所有的值都初始化为0
步骤里面省略了carry的计算
[第一步]:
c(0)=c(0)+a(0)b(0)+carry
c(1)=c(1)+a(1)b(0)+carry
...
c(n)=c(n)+a(n)b(0)+carry
c(n+1)=c(n+1)+carry
carry=0(为了不让进位带入下一次的计算)
[第二步]:
c(1)=c(1)+a(0)b(1)+carry
c(2)=c(2)+a(1)b(1)+carry
...
c(n+1)=c(n+1)+a(n)b(1)+carry
c(n+2)=c(n+2)+carry
carry=0
...
[第m+1步]:
c(m)=c(m)+a(0)b(m)+carry
c(m+1)=c(m+1)+a(1)b(m)+carry
...
c(m+n)=c(m+n)+a(n)b(m)+carry
c(m+n+1)=c(m+n+1)+carry
carry=0
看清楚,实际上c(m+n+1)就是第m+n+2位
*/
/* 以下的程序是数字倒过来输入,结果也是倒过来输入的
int* binary_multiplication(int a[], int alen, int b[], int blen){
int *c = new int[alen+blen];
memset(c, 0, sizeof(int)*(alen+blen));//将结果的每一位都清0
int carry = 0; //进位
int t; //临时变量
for(int i = 0; i < blen; i++){
for(int j = 0; j < alen; j++){
//临时变量赋值为c[i+j]
t = c[i+j];
//给c[i+j]赋值
c[i+j] = (c[i+j] + b[i]*a[j] + carry)%2;
//存放进位
carry = (t + b[i]*a[j] + carry)/2;
}
c[i+alen]=carry; //将当前最高位写上上一次加法中最后的进位
carry=0; //进位一定要在这里清零,不要带入到下一次的加法中去
}
return c;
}
*/
// 这个程序是数字是正过来输入,结果也是正过来输出的
int * binary_multiplication( int a[], int alen, int b[], int blen){
int * c = new int [alen + blen];
memset(c, 0 , sizeof ( int ) * (alen + blen)); // 将结果的每一位都清0
int carry = 0 ; // 进位
int t; // 临时变量
for ( int i = blen - 1 ; i >= 0 ; i -- ){
for ( int j = alen - 1 ; j >= 0 ; j -- ){
t = c[i + j + 1 ]; // 临时变量赋值为c[i+j+1]
c[i + j + 1 ] = (c[i + j + 1 ] + b[i] * a[j] + carry) % 2 ; // 给c[i+j]赋值
carry = (t + b[i] * a[j] + carry) / 2 ; // 存放进位
}
c[i] = carry; // 将当前最高位写上上一次加法中最后的进位
carry = 0 ; // 进位一定要在这里清零,不要带入到下一次的加法中去
}
return c;
}
int main() {
int a[] = { 1 , 1 , 1 , 0 , 0 , 0 , 0 };
int asize = sizeof (a) / sizeof ( int );
int b[] = { 1 , 1 , 1 , 0 , 1 , 1 };
int bsize = sizeof (b) / sizeof ( int );
int * result = binary_multiplication(a, asize, b, bsize);
for ( int i = 0 ; i < asize + bsize; i ++ )
cout << result[i];
cin. get ();
}
// 输出c
/*
二进制的乘法表只有两种1×1=10,1×0=0,0×0=0
其中1×1=10是要进位的
利用和十进制相似的乘法原理,做出二进制的乘法,看例子
111
× 11
----------
111
111
----------
10101
*/
#include < iostream >
#include < cstring >
using namespace std;
// 首先归纳总结:对于a(n+1位),b(m+1位)的二进制数字相乘的结果不会大于n+m+2位
// 因为a <= 2^(n+1)-1 < 2^(n+1), b <= 2^(n+1)-1 < 2^(n+1)
// 所以a*b < 2^(n+m+2) (这个数字是n+m+3位的)
// 因此,a*b的位数<=n+m+2
// 以下的程序是根据输入的两数的排列是
// a(n),a(n-1),...,a(0)和b(m),b(m-1),...,b(0)来计算的
// 所以结果是倒过来的
/* 具体算法是这样的
a(n),a(n-1)...a(0)
× b(m),b(m-1)...b(0)
------------------------------------------------------
(1) b(0)a(n), b(0)a(n-1),...., b(0)a(1), b(0)a(0)
(2) b(1)a(n), b(1)a(n-1), ... , b(1)a(1), b(1)a(0)
.
.
.
(m) b(m-1)a(n), b(m-1)a(n-1)
(m+1) b(m)a(n), b(m)a(n-1)
结果放在一个c(m+n)...c(0)的数组中,这个数组中所有的值都初始化为0
步骤里面省略了carry的计算
[第一步]:
c(0)=c(0)+a(0)b(0)+carry
c(1)=c(1)+a(1)b(0)+carry
...
c(n)=c(n)+a(n)b(0)+carry
c(n+1)=c(n+1)+carry
carry=0(为了不让进位带入下一次的计算)
[第二步]:
c(1)=c(1)+a(0)b(1)+carry
c(2)=c(2)+a(1)b(1)+carry
...
c(n+1)=c(n+1)+a(n)b(1)+carry
c(n+2)=c(n+2)+carry
carry=0
...
[第m+1步]:
c(m)=c(m)+a(0)b(m)+carry
c(m+1)=c(m+1)+a(1)b(m)+carry
...
c(m+n)=c(m+n)+a(n)b(m)+carry
c(m+n+1)=c(m+n+1)+carry
carry=0
看清楚,实际上c(m+n+1)就是第m+n+2位
*/
/* 以下的程序是数字倒过来输入,结果也是倒过来输入的
int* binary_multiplication(int a[], int alen, int b[], int blen){
int *c = new int[alen+blen];
memset(c, 0, sizeof(int)*(alen+blen));//将结果的每一位都清0
int carry = 0; //进位
int t; //临时变量
for(int i = 0; i < blen; i++){
for(int j = 0; j < alen; j++){
//临时变量赋值为c[i+j]
t = c[i+j];
//给c[i+j]赋值
c[i+j] = (c[i+j] + b[i]*a[j] + carry)%2;
//存放进位
carry = (t + b[i]*a[j] + carry)/2;
}
c[i+alen]=carry; //将当前最高位写上上一次加法中最后的进位
carry=0; //进位一定要在这里清零,不要带入到下一次的加法中去
}
return c;
}
*/
// 这个程序是数字是正过来输入,结果也是正过来输出的
int * binary_multiplication( int a[], int alen, int b[], int blen){
int * c = new int [alen + blen];
memset(c, 0 , sizeof ( int ) * (alen + blen)); // 将结果的每一位都清0
int carry = 0 ; // 进位
int t; // 临时变量
for ( int i = blen - 1 ; i >= 0 ; i -- ){
for ( int j = alen - 1 ; j >= 0 ; j -- ){
t = c[i + j + 1 ]; // 临时变量赋值为c[i+j+1]
c[i + j + 1 ] = (c[i + j + 1 ] + b[i] * a[j] + carry) % 2 ; // 给c[i+j]赋值
carry = (t + b[i] * a[j] + carry) / 2 ; // 存放进位
}
c[i] = carry; // 将当前最高位写上上一次加法中最后的进位
carry = 0 ; // 进位一定要在这里清零,不要带入到下一次的加法中去
}
return c;
}
int main() {
int a[] = { 1 , 1 , 1 , 0 , 0 , 0 , 0 };
int asize = sizeof (a) / sizeof ( int );
int b[] = { 1 , 1 , 1 , 0 , 1 , 1 };
int bsize = sizeof (b) / sizeof ( int );
int * result = binary_multiplication(a, asize, b, bsize);
for ( int i = 0 ; i < asize + bsize; i ++ )
cout << result[i];
cin. get ();
}