高精度加减乘除法

当我们遇到很大很大的数时就要用到高精度 

一、高精度加法

1.代码示例:

#include
using namespace std;
string s1,s2;
int a[10000],b[10000],c[10000];

//反转转换
void zhuanhuan(string s,int a[]){
	for(int i=0;i>s1>>s2;
	zhuanhuan(s1,a);
	zhuanhuan(s2,b);
	int la=s1.size(),lb=s2.size();
	int lc = max(la,lb)+1;
	//相加
	for(int i=1;i<=lc;i++){
		c[i]=a[i]+b[i]+c[i];
		c[i+1]=c[i]/10;
		c[i]=c[i]%10;
	}
	//去多余的零
	while(c[lc]==0&&lc>1)	{
		lc--;
	}
	for(int j=lc;j>0;j--){
		cout<

2.解析

1.首先先来了解下整体的一个操作,拿到两个字符串后,我们首先要把它转为int类=类型并加以反转,然后进行相加操作,去零操作,最后倒序输出出来。

2.(1)int lc = max(la,lb)+1;

首先我们要明确两个很大的数相加所得会有几位,这里有两种情况,一个是和两个数中大的数一样,另一种情况就是比两个数中大的那个数大一位,这里我们取第二种情况,lc之后还可以处理。

(2)c[i]=a[i]+b[i]+c[i];
         c[i+1]=c[i]/10;
         c[i]=c[i]%10;
   代码核心部分:两个数相加过程,此时我们取到的是反转后的数字,首先c[i]=a[i]+b[i]+c[i],第一位数进行相加。c[i+1]=c[i]/10,这一步是将两数相加的进位给到第二位数。c[i]=c[i]%10,这一步是将两数相加的个位留在第一位,当进入下一个循环后,c[i]=a[i]+b[i]+c[i]这一步会将这位相加的两个数和进位加到一起,以此循环。

(3)在全部相加完后可能会在最后有零,反转后零就到了前面,所以要进行去零操作。最后反转输出就行。

二、高精度减法

1.代码示例

#include
using namespace std;
string s1,s2;
int a[100],b[100];
//反转并且将字符串转为数字存到数组
void strtoint (string str,int arr[]){
	for(int i=0;i=s2.size();
	else	return s1>=s2;
} 
int main(){
	int c[100];
	cin>>s1>>s2;
	if(cmpstr(s1,s2)==false){
		swap(s1,s2);
		cout<<"-";
	}
	strtoint(s1,a);
	strtoint(s2,b);
	int la = s1.size(),lb=s2.size();
	int lc = max(la,lb);
	//进行借位相减
	for(int i=1;i<=lc;i++){
		if(a[i]1)	lc--;
	for(int j=lc;j>0;j--){
		cout<

2.解析

1.整体操作和上题类似,就是加法操作换为减法操作,同时需要加一步比较的操作,因为我们在将两个数相减时肯定是用大的减去小的。
2.(1)

bool cmpstr(string s1,string s2){
    if(s1.size()!=s2.size())    return s1.size()>=s2.size();
    else    return s1>=s2;

首先,s1.size()!=s2.size() 用来判断两个字符串的长度是否一致,若长度不同,就返回 s1.size()>=s2.size() 的结果。若 s1 的长度大于等于 s2 的长度,返回 true;反之则返回 false

然后,若两个字符串长度相同,就执行 else 分支,s1>=s2 是按照字典序比较两个字符串。在 C++ 里,string 类型重载了比较运算符,>= 会按字典序判断 s1 是否大于等于 s2。若 s1 在字典序上大于等于 s2,返回 true;反之则返回 false

之后进行调换操作

if(cmpstr(s1,s2)==false){
        swap(s1,s2);
        cout<<"-";
    }

 如果返回的是false,我们就进行调换,让s1-s2,同时让s1始终保持为较大的一个数

3. int lc = max(la,lb);

当两个数相减时,得到的最大位数与当前最大位数一样。

4.

for(int i=1;i<=lc;i++){
        if(a[i]             a[i+1]-=1;
            a[i]+=10;
        }
        c[i]=a[i]-b[i];
    }

进行错位相减,然后去零,反向输出 。

三、高精度乘法

1.代码示例:

#include
using namespace std;
string s1,s2;
int c[200],a[101],b[101];
void strtoint(string s,int a[]){
	for(int i=0;i>s1>>s2;
	int la = s1.size(),lb = s2.size();
	strtoint(s1,a);
	strtoint(s2,b);
	int lc = la+lb;
	for(int i=1;i<=la;i++){
		for(int j=1;j<=lb;j++){
			c[i+j-1] += a[i]*b[j];
			c[i+j]+=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
	}
	while(c[lc]==0&&lc>1)	lc--;
	for(int i=lc;i>0;i--){
		cout<

2.解析: 

1.首先整个流程与上两题类似

2.

lc = la+lb;

两数相乘,所得位数最大为两个位数相加

3.

for(int i=1;i<=la;i++){
        for(int j=1;j<=lb;j++){
            c[i+j-1] += a[i]*b[j];
            c[i+j]+=c[i+j-1]/10;
            c[i+j-1]%=10;
        }
    }

这里我们用到两个for循环进行相乘, c[i+j-1] += a[i]*b[j];这一步将两个具体位数相乘加上位数并放到合适的位数上,c[i+j]+=c[i+j-1]/10;这一步是给下一位增加进位,c[i+j-1]%=10;最后这一步是将两数相乘的结果的个位留下来。这里注意,前两步都是+=,是为了处理累加导致的进位,其实两个数相乘就是两个数相加。

4.去零,取反输出。

四、高精度除法

1.代码示例:

#include
using namespace std;
string s;
int a[100],c[100];
long long b;//低精度
int tmp;
void strtoint(string s,int a[]){
	for(int i=0;i>s;
	cin>>b;
	int la = s.size();
	strtoint(s,a);
	for(int i=1;i<=la;i++){
		c[i]=(tmp*10+a[i])/b;
		tmp = (tmp*10+a[i])%b;
	}
	int lc=1;
	while(c[lc]==0&&lc

2.解析:

1.这里我们将字符串变整型时,不需要取反,因为除法的运算规则就是从左到右实现的

2.

int lc=1;
    while(c[lc]==0&&lc

这里在位数设置上,本质上最大位数是与高精度的那个数的位数相同,如果有零的情况,我们就去掉。

3.

 for(int i=1;i<=la;i++){
        c[i]=(tmp*10+a[i])/b;
        tmp = (tmp*10+a[i])%b;
    }

tmp * 10 + a[i]
在模拟大整数除法时,每次处理大整数 a 的一位数字 a[i]tmp 存储的是上一步计算得到的余数,将其乘以 10 再加上当前位数字 a[i],这样做是为了把上一步的余数和当前位数字组合起来,形成一个新的临时被除数。

(tmp * 10 + a[i]) / b
用新的临时被除数除以除数 b,得到的商就是当前位的计算结果,将其存储到 c[i] 中。

(tmp * 10 + a[i]) % b
用新的临时被除数除以除数 b 后,取模运算得到的余数就是下一步计算要用到的余数,将其赋值给 tmp,以便在处理下一位数字时使用。

你可能感兴趣的:(c++,算法,开发语言,高精度)