高精度算法
学习并记录一下自己的见解,所有代码均摘自看了理解以后再抄 代号4101(顺便一提这个佬写的模板理解了真的很好用,两个构造函数使得int和char可以直接赋值 给结构体bign,还有几乎所有基本要用的运算符号都重载了。)我下面写一下大佬的代码片段说一下对大数运算的理解。
基本结构
#include<bits/stdc++.h>
using namespace std;
#define abc(i,j,k) for(int i=(int)(j);i<=(int)(k);i++)
#define cba(i,j,k) for(int i=(int)(j);i>=(int)(k);i--)
const int maxn = 5000;
struct bignum
{
int d[maxn],len;
void clean(){
while(len > 1 && !d[len-1])//不能等于1,若等于1当数为0时数组长度就为0了
len--;
}
bignum() {
memset(d,0,sizeof(d));
len=1;
}
bignum(int num) {*this = num;}
bignum(char* num){*this = num;}
bool operator <(const bignum& b) const{
if(len != b.len) return len < b.len;
for(int i = len-1; i >= 0; i--)
if(d[i] != b.d[i]) return d[i] < b.d[i];
return false;
}
string str() const{
char s[maxn]={};
abc(i,0,len-1)s[len-1-i]=d[i]+'0';
return s;
}
}
高精度加法
一位一位对着加,把进位储存,以便进行下一位的运算。最后判断一下原最高位是否产生进位即可。
bignum operator + (const bignum& b){
bignum c = *this;
int L;
abc(i,0,b.len-1){//for循环
c.d[i] += b.d[i];
if(c.d[i]>9)
{
c.d[i]%=10;
c.d[i+1]++;
}
}
L=b.len;
while(c.d[L]>9)//较小的数加完后处理大数的高位进位
{//比如9999999+1
c.d[L++]%=10;
c.d[L]++;
}
c.len=max(len,b.len);
if(c.d[L] && c.len<=L) c.len = L + 1;//最高位进位后长度加一
return c;
}
高精度减法
原理和加法基本相同,多了一个清除高位多余的零,少了最高位进位后加一
bignum operator - (const bignum& b){
bignum c = *this;
int L;
abc(i,0,b.len-1){
c.d[i] -= b.d[i];
if(c.d[i] < 0){
c.d[i]+=10;
c.d[i+1]--;//向前借位
}
}
L=b.len;
while(c.d[L] < 0){
c.d[L++]+=10;
c.d[L]--;
}
c.clean();//清除高位前面多余的零
return c;
}
高精度乘法
这个原理就是竖式计算,先是下边数的个位×上边数的每一位(不要进位,到最后会处理)之后十位,百位以此类推。
乘法这里有一个我没有理解的就是函数名称后面的const的作用,少了的话大数×int类型会报错 ,加上则不会报错。留坑后填,绝对不鸽
bignum operator * (const bignum &b)const{//竖式计算原理
bignum c;
c.len = len + b.len ;
abc(j,0,b.len-1)
abc(i,0,len-1)
c.d[i+j] += d[i] * b.d[j];//上面说的过程
abc(i,0,c.len-2)
{
c.d[i+1] += c.d[i]/10;//向高位进位
c.d[i] %= 10;
}
c.clean();//清除高位零
return c;
}
高精度除法
我个人感觉这个是最难搞的一个,好像也是类似除法的竖式运算,先取一个a=0,进入第一次循环,a=当前最高位,再用循环0-9判断j取何值时满足a<b*(j+1),后取j为除数(会出现高位0的情况,所以最后要清除高位0),后a对b取余(a=a-b*j),进入第二次循环,a*10+最高位的下一位,以此类推。
bignum operator / (const bignum& b){
bignum c = *this;
bignum a = 0;
int j;
cba(i,len-1,0)//从高位到低位取数
{
a = a*10 + d[i];
for(j = 0;j < 10;j++)if(a < b*(j+1))break;
c.d[i] = j;
a = a - b*j;//a对b取余
}
c.clean();//清除高位0
return c;
}
高精度模
上面除法最后一次循环得到的a就为余数,较为简单
bignum operator % (const bignum &b){
bignum a = 0;
int j;
cba(i,len-1,0)
{
a = a*10 + d[i];
for(j = 0;j < 10;j++)if(a < b*(j+1))break;
a = a - b*j;//余数
}
return a;
}
剩下的就是重载输入输出了我就不贴上去了,刚刚开始写博客没多久 ,可能版面较乱,讲解过乱,总之就是太菜了 ,希望不要嫌弃。