记录大数相乘的一般思路,乘法只是正数的大数相乘,数组第0位代表数组长度。
z[1]=x[1]*y[1]
z[2]=x[1]*y[2] +x[2]*y[1]
z[3]=x[1]*y[3] +x[2]*y[2]+x[3]*y[1]
…
因此可得z[i]=x[i-j+1]*y[j], for j=1到 y[0], x[0]> i-j>=0
考虑到进为问题,得到如下程序
Init(t);
t[0] = x[0] + y[0] - 1;
for (i = 1; i <= t[0]; i++)
{
sum = carry;
carry = 0;
for (j = 1; j <= y[0]; j++)
{
if ((i - j) >= 0 && (i - j) < x[0])
{
mul = x[i - j + 1];
mul = (unsigned long long)mul * y[j];
carry = carry + mul / 0x100000000;
mul = mul & 0xffffffff;
sum = sum + mul;
}
}
carry = carry + sum / 0x100000000;
t[i] = (unsigned int)sum;
}
全部代码如下
/****************************************************************************************************
大数相乘
调用方式Mul(x,y,z)
返回值,z=x*y
*****************************************************************************************************/
void Mul_Long(unsigned int x[], unsigned long long y, unsigned int *z)
{
unsigned int t[34];
unsigned long long mul;
unsigned int carry = 0;
int i;
Init(t);
Mov_Big(x, t);
for (i = 1; i <= x[0]; i++)
{
mul = x[i];
mul = mul * y + carry;
t[i] = (unsigned int)mul;
carry = (unsigned int)(mul >> 32);
}
if (carry != 0)
{
t[0]++;
t[t[0]] = carry;
}
i = t[0];
while (t[i] == 0 && i > 1) //这里有改动i>1
{
t[0]--;
i--;
}
Mov_Big(t, z);
}
void Mul_Big(unsigned int x[], unsigned int y[], unsigned int *z)
{
unsigned int t[100];
unsigned long long sum, mul = 0, carry = 0;
unsigned int i, j;
if (y[0] == 1)
Mul_Long(x, y[1], z);
else
{
Init(t);
t[0] = x[0] + y[0] - 1;
for (i = 1; i <= t[0]; i++)
{
sum = carry;
carry = 0;
for (j = 1; j <= y[0]; j++)
{
if ((i - j) >= 0 && (i - j) < x[0])
{
mul = x[i - j + 1];
mul = (unsigned long long)mul * y[j];
carry = carry + mul / 0x100000000;
mul = mul & 0xffffffff;
sum = sum + mul;
}
}
carry = carry + sum / 0x100000000;
t[i] = (unsigned int)sum;
}
if (carry != 0)
{
t[0]++;
t[t[0]] = (unsigned int)carry;
}
i = t[0];
while (t[i] == 0 && i > 1)//这里有改动
{
t[0]--;
i--;
}
Mov_Big(t, z);
}
}
能直接运行的完整代码实现大数乘法,利用devc++进行编译使用
#include
#define MAX 32
/***************************************************************************************************
初始化大数对象,且数组第一位是数组的实际长度
****************************************************************************************************/
void Init(unsigned int *x)
{
int i;
for (i = 1; i < MAX; i++)
x[i] = 0;
x[0] = 1;
}
/***************************************************************************************************
大数比较
调用方式Cmp(x, y)
返回值,若xy返回1; 若x = y返回0
*****************************************************************************************************/
int Cmp(unsigned int x[], unsigned int y[])
{
int i;
if (x[0] > y[0])
return 1;
if (x[0] < y[0])
return -1;
for (i = MAX - 1; i >= 1; i--)
{
if (x[i] < y[i])
return -1;
if (x[i] > y[i])
return 1;
}
return 0;
}
/****************************************************************************************************
大数赋值
调用方式Mov(x,y)
返回值:y被赋值为x;
*****************************************************************************************************/
void Mov_Big(unsigned int x[], unsigned int *y)
{
int i;
for (i = 0; i <= x[0]; i++)
{
y[i] = x[i];
}
if (x[0] < MAX)
for (i = x[0] + 1; i < MAX; i++)
{
y[i] = 0;
}
}
void Mov_Long(unsigned long long x, unsigned int *y)
{
int i;
if (x > 0xffffffff)
{
y[0] = 2;
y[1] = (unsigned int)x;
y[2] = (unsigned int)(x >> 32);
}
else
{
y[0] = 1;
y[1] = (unsigned int)x;
}
for (i = y[0] + 1; i < MAX; i++)
y[i] = 0;
}
/****************************************************************************************************
大数相乘
调用方式Mul(x,y,z)
返回值,z=x*y
*****************************************************************************************************/
void Mul_Long(unsigned int x[], unsigned long long y, unsigned int *z)
{
unsigned int t[34];
unsigned long long mul;
unsigned int carry = 0;
int i;
Init(t);
Mov_Big(x, t);
for (i = 1; i <= x[0]; i++)
{
mul = x[i];
mul = mul * y + carry;
t[i] = (unsigned int)mul;
carry = (unsigned int)(mul >> 32);
}
if (carry != 0)
{
t[0]++;
t[t[0]] = carry;
}
i = t[0];
while (t[i] == 0 && i > 1) //这里有改动i>1
{
t[0]--;
i--;
}
Mov_Big(t, z);
}
void Mul_Big(unsigned int x[], unsigned int y[], unsigned int *z)
{
unsigned int t[100];
unsigned long long sum, mul = 0, carry = 0;
unsigned int i, j;
if (y[0] == 1)
Mul_Long(x, y[1], z);
else
{
Init(t);
t[0] = x[0] + y[0] - 1;
for (i = 1; i <= t[0]; i++)
{
sum = carry;
carry = 0;
for (j = 1; j <= y[0]; j++)
{
if ((i - j) >= 0 && (i - j) < x[0])
{
mul = x[i - j + 1];
mul = (unsigned long long)mul * y[j];
carry = carry + mul / 0x100000000;
mul = mul & 0xffffffff;
sum = sum + mul;
}
}
carry = carry + sum / 0x100000000;
t[i] = (unsigned int)sum;
}
if (carry != 0)
{
t[0]++;
t[t[0]] = (unsigned int)carry;
}
i = t[0];
while (t[i] == 0 && i > 1)//这里有改动
{
t[0]--;
i--;
}
Mov_Big(t, z);
}
}
int main()
{
unsigned int a[33]={8, 0x7C66DDDD, 0xE8C4E481, 0x09DC3280, 0xE1E40869, 0x487D01D6, 0xF5ED0704, 0x62BF718F, 0x93DE051D };
unsigned int b[33]={8, 0x0A3EA616, 0x0C464CD7, 0xFA602435, 0x1C1C00CB, 0x5C395BBC, 0x63106512, 0x4F21E607, 0x21FE8DDA};
unsigned int c[100];
Mul_Big(a,b,c);
int i;
printf("a= ");
printf("\n ");
for(i=a[0];i>=1;i--)
printf("%llx",a[i]);
printf("\n ");
printf("\n ");
printf("b= ");
printf("\n ");
for(i=b[0];i>=1;i--)
printf("%llx",b[i]);
printf("\n ");
printf("\n ");
printf("a*b= ");
printf("\n ");
for(i=c[0];i>=1;i--)
printf("%llx",c[i]);
return 0;
}