【C++】高精度模板

📅 2026/8/2 16:32:15
【C++】高精度模板
宇宙免责申明:本文由deepseek做过更改,以及进行了语言上的优化,可能会出现错误,如有错误,请私信联系.目前高精度加法的先别抄,可能有问题.高精度计算四则运算模板详解C在 C 中内置整数类型int、long long能表示的数值范围有限long long最大约9.22×10189.22\times 10^{18}9.22×1018。当我们需要处理远超此范围的整数例如几百位的大数时就必须用数组或字符串模拟手算过程这就是高精度计算。本文基于我常用的四份模板代码分别实现高精度加法、减法、乘法高精×高精以及高精度除以低精度高精÷低精返回商和余数。所有代码均以字符串读入输出字符串结果逻辑清晰适合竞赛或工程使用。总思路:模拟竖式的加减乘除的方法.一、高精度加法思路模拟竖式加法将两个数字字符串按从低位到高位即个位在前存入vectorint。从低位到高位逐位相加同时维护进位jw。每一位结果为(a[i] b[i] jw) % 10进位为/10。最后如果进位非零补到最高位。将结果倒序转回字符串。代码函数模板#includebits/stdc.husingnamespacestd;string a,b;stringgjadd(string x,string y){intlenxx.size(),lenyy.size();intcsmax(lenx,leny);// 最长的位数vectorinta,b,sum;// 倒序存储个位在 index 0for(intilenx-1;i0;i--)a.push_back(x[i]-0);for(intileny-1;i0;i--)b.push_back(y[i]-0);inttmp0,jw0;for(inti0;ics;i){tmpjw;if(ilenx)tmpa[i];if(ileny)tmpb[i];jwtmp/10;sum.push_back(tmp%10);}if(jw!0)sum.push_back(jw);// 最高位进位string ans;for(intisum.size()-1;i0;i--)anschar(sum[i]0);returnans;}intmain(){cinab;coutgjadd(a,b);return0;}注意无需去除前导零加法不会产生多余零除非000此时保留一个0是合理的。支持任意长度只需内存足够。二、高精度减法思路模拟竖式减法但需要先判断结果符号若被减数小于减数长度短或长度相等且字典序小则交换两数并在答案前加负号-。将两数倒序存入vector。从低位到高位逐位相减若不够减则向高位借位jw1当前位加 10。最后去除结果向量末尾的多余零前导零。倒序输出若之前标记了负号则先加上。代码函数模板#includebits/stdc.husingnamespacestd;string a,b;stringgjsub(string x,string y){intlenxx.size(),lenyy.size();string ans;// 判断符号保证 x yif(lenxleny){ans-;swap(x,y);swap(lenx,leny);}elseif(lenxleny){if(xy){ans-;swap(x,y);}}intcsmax(lenx,leny);vectorinta,b,sum;for(intilenx-1;i0;i--)a.push_back(x[i]-0);for(intileny-1;i0;i--)b.push_back(y[i]-0);inttmp0,jw0;// jw 为借位for(inti0;ics;i){tmpa[i]-jw;if(ileny)tmp-b[i];if(tmp0){jw1;tmp10;}else{jw0;}sum.push_back(tmp);}// 去除前导零但至少保留一位while((int)sum.size()1sum.back()0)sum.pop_back();for(intisum.size()-1;i0;i--)anschar(sum[i]0);returnans;}intmain(){cinab;coutgjsub(a,b);return0;}注意比较两数大小时长度不同直接比长度长度相同用字符串字典序C 的string比较与数值字典序一致因为都是数字字符。借位处理是关键tmp a[i] - jw - (i leny ? b[i] : 0)若小于 0 则加 10 并标记借位。去前导零时sum是低位在前所以末尾是最高位。三、高精度乘法高精 × 高精思路模拟竖式乘法使用卷积思想将两个数倒序存入vectorint。双重循环sum[ij] a[i] * b[j]不考虑进位。统一处理进位从低位到高位将每一位sum[i]的十位及以上进位到下一位。去除结果末尾的前导零高位零。倒序输出。代码函数模板#includebits/stdc.husingnamespacestd;string a,b;stringgjmul(string x,string y){intlenxx.size(),lenyy.size();intcslenxleny;// 乘积最多 lenxleny 位vectorinta,b,sum(cs,0);for(intilenx-1;i0;i--)a.push_back(x[i]-0);for(intileny-1;i0;i--)b.push_back(y[i]-0);// 无进位累乘for(inti0;ilenx;i)for(intj0;jleny;j)sum[ij]a[i]*b[j];// 统一进位intjw0;for(inti0;ics;i){inttmpjwsum[i];jwtmp/10;sum[i]tmp%10;}// 去除前导零高位在末尾while((int)sum.size()1sum.back()0)sum.pop_back();string ans;for(intisum.size()-1;i0;i--)anschar(sum[i]0);returnans;}intmain(){cinab;coutgjmul(a,b);return0;}注意乘积位数最多为lenx leny分配sum大小为lenxleny可以保证进位不越界。进位处理放在双重循环之后更简洁且避免反复取模。去前导零时如果结果为0保留一个0。四、高精度除以低精度高精 ÷ 低精思路模拟除法竖式从高位到低位逐位求商除数b是long long类型低精度。用字符串x存储被除数从最高位开始维护当前余数ys。每一步tmp ys * 10 当前位数字商位 tmp / b余数更新为tmp % b。将所有商位存入dequeint然后去除前导零高位零。返回结构体Number包含商字符串和余数long long。代码函数模板#includebits/stdc.h#definelllonglongusingnamespacestd;string a;intb;structNumber{string shang;ll yu;};Numbergaochudi(string x,ll y){Number cur;// 除数为 0 时返回特殊标识if(y0LL){cur.shang-1;cur.yu0;returncur;}intlenxx.size();dequeinta,sum;for(inti0;ilenx;i)a.push_back(x[i]-0);ll ys0;for(inti0;ilenx;i){ll tmpys*10a[i];sum.push_back(tmp/y);ystmp%y;}// 去除前导零高位在 frontwhile((int)sum.size()1sum.front()0)sum.pop_front();string ans;for(inti0;i(int)sum.size();i)anschar(sum[i]0);cur.shangans;cur.yuys;returncur;}intmain(){cinab;Number tpgaochudi(a,b);couttp.shangendltp.yu;}注意除数为 0 时模板返回-1作为错误标识实际使用时需注意。因为低精度除法余数ys不会超过y-1用long long足够。使用deque便于从头部弹出前导零也可以改用vector然后反转。五、综合对比与使用建议运算输入类型输出类型核心技巧加法两个字符串字符串倒序相加处理进位减法两个字符串字符串判断符号借位处理去前导零乘法两个字符串字符串卷积累乘统一进位去前导零除法高精÷低精字符串 long long结构体商余数从高位模拟竖式余数迭代所有模板均以字符串作为输入输出便于处理任意长度的大整数且代码风格统一易于集成。改进扩展高精 ÷ 高精 需要更复杂的试商过程此处未提供。可以增加负数支持目前除法仅处理非负。乘法可优化为 FFT快速傅里叶变换以处理超长位数但模板中的O(n2)O(n^2)O(n2)对于几千位以内的竞赛题已足够。六、测试样例「注」觉得信不过的可以拿去测一下加法输入1234567890123456789098765432109876543210输出111111111011111111100减法输入100000000000000000001输出9999999999999999999乘法输入123456789987654321输出121932631112635269除法高精 ÷ 低精输入123456789012345678912345输出1000050986748033024余数希望这份博客能帮助你快速掌握高精度计算的核心。若有疑问欢迎留言交流完整代码已全部使用你的模板可直接复制使用。