typedef struct bigint {
unsigned arr[biglen] = { 0 };
unsigned size = 0;
};
输入函数
bigint creat(char* key) {
int len = strlen(key);
bigint ret;
ret.size = len;
for (int i = 0; i < len; i++) {
ret.arr[i] = key[len - 1 - i] - '0';
}
return ret;
}
输出函数
void big_output(const bigint& org) {
int len = org.size;
for (int k = len - 1; k >= 0; k--) {
printf("%d", org.arr[k]);
}
}
大数乘法:
根据我们乘法的步骤,在计算机上进行一个模拟即可;
如567 * 123 = (500 + 60 + 7)* 123 = 500 * 123 + 60 * 123 + 7 * 123;
这样就把大数乘以大数变成大数乘以小数再依次相加;
还有一些设计细节如将大数的所有位后移实现乘以10^k,这样每个大数都只需要乘以一个小于10的数再进行相应的后移即可。
当然,还有进位的基本方法也是需要用到的;
如下是乘法的例程:
bigint multi(bigint A, bigint B) {//大数的乘法
bigint ret, tmp;
for (int i = 0; i < B.size; i++) {//当前要乘的位(从低到高)
if (B.arr[i] == 0) continue;
copy(tmp, A);//拷贝A之后将它乘以B的某一位
for (int j = 0; j < tmp.size; j++) {
tmp.arr[j] *= B.arr[i];
}
push_back(tmp);//进位
move_back(tmp, i);//乘以10^k
ret = plus(ret, tmp);//答案加上这个组成部分
}
return ret;
}
它需要的前置函数:大家看代码直接懂
void push_back(bigint& Org) {//进位
for (int k = 0; k < Org.size; k++) {
Org.arr[k + 1] += Org.arr[k] / 10;
Org.arr[k] = Org.arr[k] % 10;
if (k == Org.size - 1 && Org.arr[k + 1] > 0) Org.size++;
}
}
void move_back(bigint& Org, int times) {//后移times位实现乘以10^k
while (times--){
for (int k = Org.size; k > 0; k--) {
Org.arr[k] = Org.arr[k - 1];
}
Org.arr[0] = 0;
Org.size++;
}
}
bigint plus(bigint A, bigint B) {//两个大数的加法
bigint ret, tmp;
if (A.size >= B.size) {//将较大的那个数作为加法的主体
copy(ret, A);
copy(tmp, B);
}
else {
copy(ret, B);
copy(tmp, A);
}
for (int k = 0; k < ret.size; k++) {
ret.arr[k] += tmp.arr[k];//每一位从小到大依次相加
push_back(ret);//进位
}
return ret;
}
这里提一下&表示引用即此时形参并非存储实参的值而是实参本身,函数可以在函数内直接改变实际参数的值,这是C++的内容但通过指针变量也能一样实现;
大数的快速幂:
快速幂算法:如A^11 = A^1 * A^2 * A^8;
通过将指数转化成二进制,然后通过创建一个不断自乘的中间量,在满足该位为1时将输出量乘以该中间量,最终达到进行 log n 次乘法实现指数运算的目的。
对于大整数快速幂还需要一个返回大整数余2的余数的函数和大整数不断除以二的函数,这里我们统一实现;
大数的快速幂算法如下:
bigint big_pow(bigint& X, bigint Y) {
bigint ret, tmpX;
ret.arr[0] = 1; ret.size = 1;
copy(tmpX, X);
while (Y.size != 0) {
if (!Is2(Y)) {
ret = multi(ret, tmpX);
}
tmpX = multi(tmpX, tmpX);
}
return ret;
}
前置函数:
bool Is2(bigint& org) {
bool ret = 0;
if (org.arr[0] % 2 == 0) ret = 1;
org.arr[0] /= 2;
for (int k = 1; k < org.size; k++) {
if (org.arr[k] % 2 == 0) {
org.arr[k] /= 2;
}
else {
org.arr[k] /= 2;
org.arr[k - 1] += 5;
}
}
if (org.arr[org.size - 1] == 0) {
org.size--;
}
return ret;
}
运行截图:
不过经过测试两个数中只能有一个数很大不然会超出堆栈。