大整数的相关操作
1、给定条件下的数据范围:1 <= A <=
1
0
5
10^5
105 ,1 <= B <=
1
0
5
10^5
105
2、加载数据:将输入的数据作为字符存储,实现大整数数据的加载
3、数据处理:使用C++的vector向量处理输入数据,并且数据低位在前( string “12344” --> vector {4,4,3,2,1} )
4、执行相关操作:通过以下方法实现加、减、乘、除
1、加法操作
/*
* param : 加法因子 A (vector<int>) , 加法因子 B (vector<int>)
* return : 加法结果 C (vector<int>)
*/
vector<int> add(vector<int> &A, vector<int>&B){
vector<int> C; //定义返回结果C
int t=0; //定义进位值
for(int i=0;i<A.size()||i<B.size();i++){
/* 从低位开始进行对应位的相加,即在第i位有:(式子右边的t表示i-1位上进行加运算后的进位值)
* 1. t = t+A[i]+B[i] , i<A.size() and i<B.size() 第i位上A和B均有值
* 2. t = t+A[i] , i<A.size() and i>=B.size() 第i位上仅A有值
* 3. t = t+B[i] , i<B.size() and i>=A.size() 第i位上仅B有值
*/
if(i<A.size()) t += A[i];
if(i<B.size()) t += B[i];
// ( t mod 10 ), 即第i位的结果
C.push_back(t%10);
// t>10 表示有进位,进位值为 t / 10 = t
// t<10 表示无进位,进位值为 t / 10 = 0
t /= 10;
}
//如果在A和B的最后一位上进行加运算仍有进位(t=1),即添加至结果中
if(t) C.push_back(1);
return C;
}
2、减法操作
/*
* param : 被减数 A (vector<int>) , 减数 B (vector<int>)
* return : 加法结果 C (vector<int>)
*/
vector<int> sub(vector<int> &A,vector<int> &B){
vector<int> C; //定义返回结果C
int t=0; //定义借位值
for(int i=0;i<A.size()||t;i++){
// 从低位开始进行对应位的相减
t = A[i] - t; //被减数中第i位的值A[i]需要先减去第i-1位上的借位值
if(i<B.size()) t -= B[i]; //然后当减数B第i位上有值时,需要减去B[i]
/* 第i位的结果是:(t+10) mod 10, 当在第i位上进行减操作的时候:
* 1. 若t<0,则说明需要向A[i+1]借位
* 2. 若t>=0,则不需要借位
*/
C.push_back((t+10)%10);
if(t<0) t = 1; //发生借位,则借位值为1
else t = 0; //否则为0
}
//去除前导0,否则会出现:333- 332 = 001 的情况
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
因为当进行减法操作时会出现A-B(A<B)的情况,所以需要考虑正负,而通过如下的比较函数可以避免在sub函数中考虑正负,如下所示:
bool cmp(vector<int> &A, vector<int> &B){
/* 当A和B的长度不一致时返回长度较大的那个
* A : { 1, 4 , 5 , 6 , 3 , 2 } --> 236541 √
* B : { 3, 3 , 6 , 7 , 8 } --> 87633
*/
if(A.size()!=B.size()) return A.size()>B.size();
//当A和B的长度一致时从高位开始遍历A和B
for(int i=A.size()-1;i>=0;i--){
/* 当A[i]和B[i]不相等时返回值较大的那个
* A : { 1, 4 , 5 , 6 , 3 , 2 } --> 236541
* B : { 3, 3 , 6 , 6 , 3 , 2 } --> 236633 √
* 0 1 2 3 4 5
* < = = =
*/
if(A[i]!=B[i]) return A[i]>B[i];
}
return true;
}
3、乘法操作
/*
* param : 乘法因子 A (vector<int>) , 乘法因子 B (vector<int>)
* return : 乘法结果 C (vector<int>)
*/
vector<int> multi(vector<int> &A,vector<int> &B){
/* 构造返回结果C,设置其长度为A和B的长度之和,该长度满足任意情况
* A : { a3 , a2 , a1 }
* B : { b3 , b2 , b1 }
* C = A × B = { a3·b3 , a3·b2 + a2·b3 ,
* a3·b1 + a2·b2 + a1·b3 , a2·b1 + a1·b2 , a1·b1 }
* 因为a3·b3的结果可能大于10,所以需要保证C的长度为A和B的长度和
*/
vector<int> C(A.size()+B.size(),0);
for(int i=0;i<A.size();i++){
for(int j=0;j<B.size();j++){
//先将A和B的不同位上的数相乘,然后将结果添加到C的对应位上
C[i+j] += A[i] * B[j]; //使用+=是因为第i+j位上可能存在其他值
}
}
int t=0; //定义进位值
//遍历初始结果C,对每一位上的数据进行处理,因为其中的某位数据可能是两位数或三位数
for(int i=0;i<C.size();i++){
t = t + C[i]; //等式右侧的t表示第i-1位上的进位值
C[i] = t%10; //第i位上的值取该位上C[i]的模即可
t/=10; //然后通过t/10来求得进位值
}
//去除前导0,否则会出现:333 × 0 = 000 的情况
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
4、除法操作
/*
* param : 被除数 A (vector<int>) , 除数 B (vector<int>) , 余数 r (vector<int>)
* return : 除法结果 C (vector<int>)
*/
vector<int> div(vector<int> &A, vector<int> &B, vector<int> &r)
vector<int> C; //定义返回结果C
/* 假设 A={1,2,3,4}-->"4321", B={1,1,2}-->"211", 执行的过程如下:
* 1. j=3
* 第一步: r={2,3,4}-->"432"
* 因为 r="432" > B="211",所以 r=sub(r,B) => r="432"-"211"="221"
* 第二步: r={1,2,2}-->“221”
因为 r="221" > B="211",所以 r=sub(r,B) => r="221"-"211"="10"
* 第三步: r={0,1}-->"10"
* 因为 r="10" < B="211",所以需要补充一位,即使j值加1
* 因为执行了两次sub操作,即第一位的商值为2 => C={2}
* 2. j=4
* 第一步: r={1,0,1}-->"101"
* 因为 r="101" < B="211",所以需要补充一位,即使j值加1
* 因为执行了零次sub操作,即第二位的商值为0 => C={2,0}
* 并且为了使商值C满足数据格式的要求,即低位在前,需要使其反转 C={0,2}
* 3. j=5
* 因为 j=5 > A.size(),所以循环结束,得出结果:
* 商:C={0,2} --> "20"
* 余数:r={1,0,1} --> "101"
*/
int j = B.size(); //获取B的长度值
r.assign(A.end()-j,A.end()); //先将A{n-j..n}的值分配给余数r
while(j<=A.size()){
int k=0; //定义商值
//循环执行减操作,前提是r要大于B
while(cmp(r,B)){
r = sub(r,B); //更新r向量的值
k++; //更新商值
}
C.push_back(k); //添加商值
//使r向量向后补充一位,使之能够继续执行循环减操作
if(j<A.size()) r.insert(r.begin(),A[A.size()-j-1]);
//去除r向量的前导0,否则出现1101/11 => r=01/11 的情况
if(r.size()>1&&r.back()==0) r.pop_back();
j++; //j指针向右移一位,即表示向量r向后补充一位
}
reverse(C.begin(),C.end()); //反转商值向量C,使其满足数据格式要求
//去除C向量的前导0,否则出现1101/11 => C="0100" 的情况
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
执行示例
int main(){
string a,b; //定义a和b为string字符串
cin>>a>>b; //输入a和b
vector<int> A,B,r; //定义A、B和r向量表示a、b和余数
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0'); //处理字符串a得到A
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0'); //处理字符串b得到B
vector<int> C; //定义返回结果C
/* 1.加法示例
* C = add(A,B);
*/
/* 2.减法示例
* if(cmp(A,B)){
* C = sub(A,B);
* }else{
* C = sub(B,A);
* printf("-");
* }
*/
/* 3.乘法示例
* C = multi(A,B);
*/
/* 4.除法示例
* if(cmp(A,B)){
* C = div(A,B,r);
* }else{
* C.push_back(0);
* r.assign(A.begin(),A.end());
* }
*/
return 0;
}