• [总结/模板]高精度算法(四则运算)



    当我们在进行四则运算的时候,如果需要处理的数据范围超过正常的数据类型,为了保证答案的正确性可以使用高精度算法。
    高精度算法就是在模拟我们进行四则运算的过程。
    不要试图指望_int128这种东西,用了也无卵用并且gcc也不支持。
    在了解高精度算法之前,先让我们了解一些小知识:

    1. 如何将字符串转化为数组
    2. 高精度的比较

    1. 字符串转化为数组:

    我们依次扫描的字符串是由高位指向低位的,而我们计算的时候却是由低位向高位进行的。这时候我们可以用string.size-i巧妙地转化。

    这里给出string类型和char类型两种方法:
    String:

    string A,B;
    int a[100]={0},b[100]={0};
    int na=A.length();  
    for(i=1;i<=na;i++)  a[i]=A[na-i]-'0';  
    int nb=B.length();  
    for(i=1;i<=nb;i++)  b[i]=B[nb-i]-'0';  
    

    Char:

    char A[100],B[100];
    scanf("%s%s",A,B);
    int na=strlen(A),nb=strlen(B);
    for(int i=0;i<na;i++) a[na-i]=A[i]-'0';
    for(int i=0;i<nb;i++) b[nb-i]=B[i]-'0';
    

    2. 高精度的比较:

    首先按位数比较,位数多的数一定越大(正整数范围);其次按照每位整数大小比较,由高位至低位依次比较大小。若以上两条件都没有返回判断,那么这两个大整数相等。

    inline bool compare_size(){
    	if(na>nb) return 1;
    	if(na<nb) return 0;
    	for(int i=na;i>=1;i--){
    		if(a[i]>b[i]) return 1;
    		if(a[i]<b[i]) return 0;
    	}
    	return -1;
    }
    

    接下来是正文


    一、高精度加法

    P1601 A+B Problem(高精)
    高精度加法是相对简单的一类高精度。值得注意的地方是建立一个变量ext(extra)表示当前位的进位,并且要删掉前导0。
    Code:

    #include<bits/stdc++.h>
    #define N 1000010
    using namespace std;
    char A[N],B[N];
    int a[N],b[N],c[N],na,nb,nc,ext;//数组c存放最终结果 
    inline void change_to_number(){
    	for(int i=0;i<na;i++) a[na-i]=A[i]-'0';
    	for(int i=0;i<nb;i++) b[nb-i]=B[i]-'0';
    }//转化成单个数字 
    int main()
    {
    	scanf("%s%s",A,B);
    	na=strlen(A),nb=strlen(B);
    	change_to_number();
    	nc=1;
    	while(nc<=na||nc<=nb){
    		c[nc]=a[nc]+b[nc]+ext;
    		ext=c[nc]/10;//求进位 
    		c[nc]%=10;nc++;
    	}
    	c[nc]=ext;
    	if(!c[nc]) nc--;
    	for(int i=nc;i>=1;i--) printf("%d",c[i]); //倒序输出
    	return 0;
    }
    

    二、高精度减法

    P2142 高精度减法
    高精度减法的借位处理与加法类似,被减数不够减便向高位借一位,并在该位加10再处理。
    处理后产生的前导0,需要我们手动处理。
    最后需要解决答案是负数的问题,这里给出一种很简单的方法:预先比较被减数与减数的大小,如果被减数小于减数,那么交换这两个数并在答案前面加上'-'
    以上就完成了高精度减法的处理,细节见代码:
    Code:

    #include<bits/stdc++.h>
    #define N 20010
    using namespace std;
    char A[N],B[N];
    int a[N],b[N],na,nb;
    inline bool compare_size(){//大整数比较
    	if(na>nb) return 1;
    	if(na<nb) return 0;
    	for(int i=na;i>=1;i--){
    		if(a[i]>b[i]) return 1;
    		if(a[i]<b[i]) return 0;
    	}
    	return 1;
    }
    inline void change_to_number(){
    	for(int i=0;i<na;i++) a[na-i]=A[i]-'0';
    	for(int i=0;i<nb;i++) b[nb-i]=B[i]-'0';
    }
    int main()
    {
    	scanf("%s%s",A,B);//A是被减数,B是减数 
    	na=strlen(A),nb=strlen(B);
    	change_to_number();
    	if(compare_size()){//被减数大于减数
    		for(int i=1;i<=na;i++){
    			a[i]-=b[i];
    			if(a[i]<0) a[i+1]--,a[i]+=10;//不够减,进位
    		}
    		while(!a[na]&&na>1) na--;//去掉0
    		for(int i=na;i>=1;i--) printf("%d",a[i]);
    	}
    	else{//小于减数
    		printf("-");
    		for(int i=1;i<=nb;i++){
    			b[i]-=a[i];
    			if(b[i]<0) b[i+1]--,b[i]+=10;
    		}
    		while(!b[nb]&&nb>1) nb--;
    		for(int i=nb;i>=1;i--) printf("%d",b[i]);
    	}
    	return 0;
    }
    

    三、高精度乘法

    P1303 A*B Problem
    在小学大家一定都练习过竖式乘法,所以高精乘与我们小学学过的方法是一样的,被乘数的第(i)位与乘数的第(j)位落在第(i+j-1)位(不懂得话可以手动模拟一下),如果结果大于10,那么进位并将自身(mod10)。具体详见代码:
    Code:

    #include<bits/stdc++.h>
    #define N 250000
    using namespace std;
    char A[N],B[N];
    int a[N],b[N],c[N],na,nb;
    inline void change_to_number(){
    	for(int i=0;i<na;i++) a[na-i]=A[i]-'0';
    	for(int i=0;i<nb;i++) b[nb-i]=B[i]-'0';
    }
    int main()
    {
    	scanf("%s%s",A,B);
    	na=strlen(A),nb=strlen(B);
    	change_to_number();
    	for(int i=1;i<=na;i++)
    		for(int j=1;j<=nb;j++){
    			c[i+j-1]+=a[i]*b[j];
    			c[i+j]+=c[i+j-1]/10;//进位
    			c[i+j-1]%=10;
    		}
    	int nc=na+nb;//最终位数
    	while(nc>1&&!c[nc]) nc--;//去除前导0
    	for(int i=nc;i>=1;i--) printf("%d",c[i]);
    	return 0;
    }
    

    四、高精度除法

    给出高精除低精的算法,每次按位除以除数,并不断更新余数。
    Code:

    #include<bits/stdc++.h>
    #define N 10010
    using namespace std;
    char A[N],C[N];
    int a[N],c[N],b,na,nc,rest;
    int main()
    {
        scanf("%s%d",A,&b);
        na=strlen(A);
        for(int i=1;i<=na;i++) a[i]=A[i-1]-'0';
        for(int i=1;i<=na;i++){
            c[i]=(rest*10+a[i])/b;
            rest=(rest*10+a[i])%b;
        }
        while(!c[nc]&&nc<na) nc++;
        for(int i=nc;i<=na;i++) printf("%d",c[i]);
        return 0;
    }
    

    pic.png

  • 相关阅读:
    一个群发站内信的设计
    javascript typeof 小结
    setInterval,setTimeout的用法
    C#中常见异常类
    输入框关闭自动完成功能
    【转】javascript判断一个元素是否数组
    jquery的动态统计输入字符数方法
    giedview绑定数据格式化字符串
    jQuery 1.4单独为某个动画动作设效果
    GridView行编辑中找DropDownList控件
  • 原文地址:https://www.cnblogs.com/cyanigence-oi/p/11758988.html
Copyright © 2020-2023  润新知