/*
二进制大整数的乘法:
请设计一个有效的算法,可以进行两个n 位二进制大整数的乘法运算
设x = 3141, A = 31 B=41
y = 5327, C = 53,D=27
x*y = AC*2^n + (AD + BC)*2^(n/2) + BD
= AC*2^n + ((A-B)*(D-C) + A*C + B*D)*2^n + BD //少算一次乘法
递归基:当只有一个元素的时候
下面实现的是十进制大整数乘法
输入:
3141 5327 10(必须确保位数为偶数位)
9 11 2(必须确保该十进制数对应的二进制数是位数相同的)
输出:
16732107
99
731074749
*/
/*
这里其实没有用到分治,因为需要分解数字,下次考虑到x,y均小于10的时候再计算
*/
#include <stdio.h>
#include <iostream>
using namespace std;
bool g_valid;//全部标记变量
int sign(int a)//获取整数a的符号
{
return a > 0 ? 1 : -1;
}
int myAbs(int a)
{
return a > 0 ? a : -1*a;
}
int digitCount(int a,int iBase)
{
int iTotalDigit = 0;
do
{
a /= iBase;//获取下一位
iTotalDigit++;
}while(a);
return iTotalDigit;
}
int getBack(int a,int iBase,int iTotalDigit)//iBase为基数
{
if(a <= 0)//这里必须确保a是正数
{
g_valid = false;
return -1;
}
/*只需要把后半段计算出来,然后用前半段去减。问题转化为如何求出后半段。1234:必须知道总共位数/2,求一个整数的位数,
可以用它自己不断和它本身减一去取与,很快可以求解。
设置一个计数器,当达到总位数一半的时候,停止计数,然后将数组中保存的从低位到高位的累加和输出
*/
int iCnt = 0;
int iSum = 0;
int iFactor = 1;
do
{
iSum += iFactor*(a % iBase);
iFactor *= iBase;
a /= iBase;
iCnt++;
if(iCnt == iTotalDigit/2)
{
break;
}
}while(a);
return iSum;
}
//返回iBase^iExp
int myPow(int iBase,int iExp)
{
if(iExp == 1)//递归出口
{
return iBase;
}
int iRet = myPow(iBase,iExp/2);
iRet *= iRet;
if(iExp % 2 == 1)
{
iRet *= iBase;
}
return iRet;
}
int multiply(int x,int y,int iBase)
{
//预处理符号
int iSign = sign(x) * sign(y);
x = myAbs(x);
y = myAbs(y);
//鲁棒性
int iTotalDigitX = digitCount(x,iBase);
int iTotalDigitY = digitCount(y,iBase);
//
if(iTotalDigitX != iTotalDigitY)
{
g_valid = false;
return -1;
}
//递归出口,如果都为1,返回乘积的符号
if(x == 1 && y == 1)
{
return iSign;
}
else
{
//计算每一个数的前半部分和后半部分
int iDivideNum = myPow(iBase,iTotalDigitX/2);
int iBackX = getBack(x,iBase,iTotalDigitX);
//靠计算错了,例如5341计算出的是5300,还要除以100
int iFrontX = ( x - iBackX ) / iDivideNum;
int iBackY = getBack(y,iBase,iTotalDigitY);
int iFrontY = ( y - iBackY ) / iDivideNum;
//计算每一部分乘积
int iM1 = iFrontX * iFrontY;
int iM2 = iBackX * iBackY;
int iM3 = (iFrontX - iBackX) * (iBackY - iFrontY) + iM1 + iM2;
int iRet = iSign * ( iM1*myPow(iBase,iTotalDigitX) + iM3*myPow(iBase,iTotalDigitX/2) + iM2 );
return iRet;
}
}
void process()
{
int x,y,iBase;
while(EOF != scanf("%d %d %d",&x,&y,&iBase))
{
g_valid = true;
int iRet = multiply(x,y,iBase);
if(g_valid)
{
printf("%d\n",iRet);
}
else
{
printf("您输入的两个整数%d %d的位数不一致,请检查!\n",x,y);
}
}
}
int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}
算法设计与分析:第三章 分治 3.3二进制大整数的乘法
原文作者:大整数乘法问题
原文地址: https://blog.csdn.net/qingyuanluofeng/article/details/47189237
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/qingyuanluofeng/article/details/47189237
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。