【算法总结】数学问题-高精度整数
【算法总结】高精度整数
我们首先明确高精度整数的保存形式,我们常用如下结构体来保存一个高精度整数
struct biginteger { int digit[1000];//保存大整数中若干位的数字,暂且使用每4位为一个单位保存 int size;//size是digit数组中第一个我们还未使用的数组单元,即digit数组下一个存储单元的角标 };
一、高精度加法
例 4.11 a+b
AC代码
#include<cstdio> #include<cstring> struct biginteger//高精度整数结构体 { int digit[1000];//保存大整数中若干位的数字,暂且使用每4位为一个单位保存 int size;//size是digit数组中第一个我们还未使用的数组单元,即digit数组下一个存储单元的角标 void init()//对结构体的初始化 { for (int i = 0; i < 1000; i++)digit[i] = 0;//所有数位清0 size = 0;//没有一个单元被使用 } void set(char str[])//从字符串中提取整数存入大数数组,单元内顺序,单元外倒序存储 { init();//对结构体的初始化 int L = strlen(str);//计算字符串长度 for (int i = L - 1, j = 0, t = 0, c = 1; i >= 0; i--)//从最后一个字符开始倒序遍历字符串,j控制每4个字符转换为一个数字存入数组,t临时保存字符转换为数字的中间值,c表示当前位的权重,按1,10,100,1000变化 { t += (str[i] - '0')*c;//计算四位数中当前字符代表的数值 j++;//数位增加 c *= 10;//权重更新 if (j == 4 || i == 0)//若已经连续转换4个字符,或者已到达最后一个字符 { digit[size++] = t;//将这四个字符代表的四位数存入数组,size移动到下一个单位 j = 0;//更新 t = 0;//更新 c = 1;//更新 } } } void output()//将该高精度整数输出 { for (int i = size - 1; i >= 0; i--) { if (i != size - 1)printf("%04d", digit[i]);//不是最高位则当前数组不足4位时用0补充 else printf("%d", digit[i]);//最高位不用补充0 } printf(" "); } biginteger operator + (const biginteger &A)const//重载加法运算符 { biginteger ret;//返回值,两数相加的结果 ret.init();//初始化 int carry = 0;//进位,初始值为0 for (int i = 0; i < A.size || i < size; i++) { int tmp = A.digit[i] + digit[i] + carry;//计算两个整数当前位以及来自低位的进位和 carry = tmp / 10000;//计算该位的进位 tmp %= 10000;//去掉进位部分 ret.digit[ret.size++] = tmp;//保存该位结果 } if (carry != 0) ret.digit[ret.size++] = carry;//最高位的进位 return ret; } }a, b, c;//结构体别名 char str1[1002], str2[1002]; int main() { while (scanf("%s%s", str1, str2) != EOF) { a.set(str1); b.set(str2); c = a + b; c.output(); } return 0; }
二、高精度乘法
这里指的乘法运算一般为高精度整数乘以一般小整数的运算。
例4.12 N的阶乘
AC代码
#include<cstdio> #include<cstring> struct biginteger//高精度整数结构体 { int digit[1000];//保存大整数中若干位的数字,暂且使用每4位为一个单位保存 int size;//size是digit数组中第一个我们还未使用的数组单元,即digit数组下一个存储单元的角标 void init()//对结构体的初始化 { for (int i = 0; i < 1000; i++)digit[i] = 0;//所有数位清0 size = 0;//没有一个单元被使用 } void set(int x) { init();//对结构体的初始化 do//对一个小整数4位一个单位分解依次存入digit中 { digit[size++] = x % 10000; x /= 10000; } while (x != 0); } void output()//将该高精度整数输出 { for (int i = size - 1; i >= 0; i--) { if (i != size - 1)printf("%04d", digit[i]);//不是最高位则当前数组不足4位时用0补充 else printf("%d", digit[i]);//最高位不用补充0 } printf(" "); } biginteger operator * (int x)const//重载加法运算符 { biginteger ret;//返回值 ret.init();//初始化 int carry = 0;//进位,初始值为0 for (int i = 0; i < size; i++) { int tmp = x * digit[i] + carry;//计算小整数乘以当前位数字来自低位的进位和 carry = tmp / 10000;//计算该位的进位 tmp %= 10000;//去掉进位部分 ret.digit[ret.size++] = tmp;//保存该位结果 } if (carry != 0) ret.digit[ret.size++] = carry;//最高位的进位 return ret; } }a;//结构体别名 char str1[1002], str2[1002]; int main() { int n; while (scanf("%d", &n) != EOF) { a.init(); a.set(1);//a的初始值为1 for (int i = 1; i <= n; i++) { a = a * i; } a.output(); } return 0; }