在C/C++中,int占一个机器字长,32位机中则占4个字节,即[-2^31,2^31-1](10的9次方数量级)。不管是32位还是64位机,long long占8个字节,即[-2^63,2^63-1](10的18次方数量级)。
如果超过该数量级,应该使用高精度算法。
1 加
1、将两个加数逆序存储在两个int数组中。(逆序的原因是方便操作和数据对齐,加法计算都是从低位开始操作,逆序的话就把最低位存在a[0]、b[0]这个位置)
2、两个加数的和,它的最大长度是较长的那个加数的长度+1(lc=max(la,lb)+1)。如果和不是最大长度的话,就会有前导0,需要去除。
3、核心算法:
c[i]+=a[i]+b[i];
c[i+1]=c[i]/10;
c[i]=c[i]%10;
#include<iostream>
#include<string>
using namespace std;
const int N=100;//大数的长度
int a[N],b[N],c[N];
void add(string s1,string s2){
for(int i=0;i<s1.length();i++){
a[s1.length()-i]=s1[i]-'0';//逆序存储
}
for(int i=0;i<s2.length();i++){
b[s2.length()-i]=s2[i]-'0';
}
int lc=max(s1.length(),s2.length())+1;
for(int i=1;i<=lc;i++){
c[i]+=a[i]+b[i];//有进位,所以是+=
c[i+1]=c[i]/10;
c[i]=c[i]%10;
}
while(lc>1&&c[lc]==0) lc--;//去前导0
for(int i=lc;i>=1;i--){//逆序输出
cout<<c[i];
}
cout<<endl;
}
int main(){
string s1,s2;
cin>>s1>>s2;
add(s1,s2);
return 0;
}
2 减
1、比较大小,用大的减小的,如果s1大于s2,输出。如果小于,就添一个负号。
2、将被减数和减数逆序存储在int数组中。(逆序:和前面的加法一样,减法也是从低位开始计算的)
3、计算得到的差,最长长度也只有被减数那么长(lc=la)。如果没有到达最长长度,需要去除前导0
4、核心算法
if(a[i]<b[i]){
a[i+1]--;
a[i]+=10;
}
c[i]=a[i]-b[i];
#include<iostream>
#include<string>
using namespace std;
const int N=100;//大数的长度
int a[N],b[N],c[N];
bool cmp(string s1,string s2){
if(s1.length()!=s2.length()) return s1.length()>s2.length();
for(int i=0;i<s1.length();i++){
if(s1[i]!=s2[i]) return s1[i]>s2[2];
}
return true;
}
void subtract(string s1,string s2){
for(int i=0;i<s1.length();i++){
a[s1.length()-i]=s1[i]-'0';//逆序存储
}
for(int i=0;i<s2.length();i++){
b[s2.length()-i]=s2[i]-'0';
}
int lc=s1.length();
for(int i=1;i<=lc;i++){
if(a[i]<b[i]){
a[i+1]--;
a[i]+=10;
}
c[i]=a[i]-b[i];
}
while(lc>1&&c[lc]==0) lc--;//去前导0
for(int i=lc;i>=1;i--){//逆序输出
cout<<c[i];
}
cout<<endl;
}
int main(){
string s1,s2;
cin>>s1>>s2;
if(cmp(s1,s2)){
subtract(s1,s2);
}else{
cout<<"-";
subtract(s2,s1);
}
return 0;
}
3 乘
1、逆序存储两个乘数
2、乘积的最长长度为两个乘数的长度之和(lc=la+lb)。
3、a[i]*b[j]位置对应c[i+j-1]位置。核心代码:
c[i+j-1]+=a[i]*b[j];
c[i+j]+=c[i+j-1]/10;
c[i+j-1]%=10;
#include<iostream>
#include<string>
using namespace std;
const int N=100;
int a[N],b[N],c[N];
void multiply(string s1,string s2){
for(int i=0;i<s1.length();i++){
a[s1.length()-i] =s1[i]-'0';//逆序存储
}
for(int i=0;i<s2.length();i++){
b[s2.length()-i] =s2[i]-'0';
}
int lc=s1.length()+s2.length();//乘积的最长长度
for(int i=1;i<=s1.length();i++){
for(int j=1;j<=s2.length();j++){
c[i+j-1]+=a[i]*b[j];
c[i+j]+=c[i+j-1]/10;
c[i+j-1]%=10;
}
}
while(lc>1&&c[lc]==0) lc--;
for(int i=lc;i>=1;i--){
cout<<c[i];
}
cout<<endl;
}
int main(){
string s1,s2;
cin>>s1>>s2;
multiply(s1,s2);
return 0;
}
4 除
4.1 高精度÷低精度
1、将高精度的被除数存入int数组,不需要逆序存储,因为除法是从高位开始的。
2、商的最长长度为被除数的长度(lc=la,实际上是lc=la-lb+1,但是b不是高精度的不方便求,这里长度放大一些也没关系),如果没有达到,需要去除前导0
3、核心算法
c[i]=(r*10+a[i])/b;
r=(r*10+a[i])%b;
#include<iostream>
#include<string>
using namespace std;
const int N=100;
int a[N],c[N];
void divide(string s1,int b,int &r){
for(int i=0;i<s1.length();i++){
a[i+1]=s1[i]-'0';//不需要逆序存储
}
int lc=s1.length();
for(int i=1;i<=lc;i++){
c[i]=(r*10+a[i])/b;
r=(r*10+a[i])%b;
}
int x=1;
while(c[x]==0&&x<lc) x++;//去前导0
for(int i=x;i<=lc;i++){
cout<<c[i];
}
cout<<endl;
}
int main(){
string s1;
int b;
cin>>s1>>b;
int r=0;
divide(s1,b,r);
cout<<"余数为:"<<r<<endl;
return 0;
}
4.2 高精度÷高精度
减法模拟除法,因此本质上是减法,所以存储时需要倒序存储。
以下默认被除数大于等于除数,如果小于的话,答案为0,余数为被除数。
1、将被除数和除数倒序存储在int数组中。
2、商的最长长度为lc=la-lb+1
3、减法模拟。核心算法:
for(int i=lc;i>=1;i--){
meset(temp,0,sizeof(temp));//temp也是高精度的,将其清空
高精度除数左移lc-1位,存在temp中
while(a>=temp){//高精度比较
a[i]++;
a=a-temp;//高精度减法 最后的余数也就是a
}
}
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int N=100;
int a[N],b[N],c[N],temp[N];//temp数组为除数左移之后的值
bool cmp(string s1,string s2){
if(s1.length()!=s2.length()) return s1.length()>s2.length();
for(int i=0;i<s1.length();i++){
if(s1[i]!=s2[i]) return s1[i]>s2[i];
}
return true;
}
//除数左移
void move(int b[],int temp[],int x){
for(int i=1;i<=x;i++){
temp[i]=0;
}
for(int i=1;i<=b[0];i++){
temp[i+x]=b[i];
}
temp[0]=b[0]+x;
}
bool compare(int a[],int temp[]){
if(a[0]!=temp[0]) return a[0]>temp[0];
for(int i=a[0];i>=1;i--){
if(a[i]!=temp[i]) return a[i]>temp[i];
}
return true;
}
//减法 a=a-temp
void jian(int a[],int temp[]){
for(int i=1;i<=a[0];i++){
if(a[i]<temp[i]){
a[i+1]--;
a[i]+=10;
}
a[i]=a[i]-temp[i];
}
while(a[0]>1&&a[a[0]]==0) a[0]--;
}
void divide(string s1,string s2){
a[0]=s1.length();//用a[0]存储它的长度
b[0]=s2.length();
for(int i=0;i<s1.length();i++){
a[s1.length()-i]=s1[i]-'0';//逆序存储
}
for(int i=0;i<s2.length();i++){
b[s2.length()-i]=s2[i]-'0';
}
int lc=s1.length()-s2.length()+1;
for(int i=lc;i>=1;i--){
memset(temp,0,sizeof(temp));
move(b,temp,i-1);//将除数左移i-1位 存在temp数组中
while(compare(a,temp)){//a>=temp
c[i]++;
jian(a,temp);//a=a-temp
}
}
while(lc>1&&c[lc]==0) lc--;
for(int i=lc;i>=1;i--){
cout<<c[i];
}
cout<<endl;
cout<<"余数为:";
//余数即为改变后的a
for(int i=a[0];i>=1;i--){
cout<<a[i];
}
cout<<endl;
}
int main(){
string s1,s2;
cin>>s1>>s2;
divide(s1,s2);
return 0;
}
标签:lc,temp,高精度,int,s2,s1,大数,--,算法
From: https://blog.csdn.net/m0_73801775/article/details/136823173