4 条题解

  • 4

    C++高精度函数写法

    #include <iostream>
    #define N 10010
    
    using namespace std;
    
    string a, b;
    //以下三个函数高精除法(取余)要用到
    int compare(int x[], int y[]){ //比较两个高精数据(数组)大小,x大于y返回1,小于返回-1,等于返回0
    	if(x[0] != y[0]) return x[0] > y[0] ? 1 : -1;
    	for(int i = x[0]; i; i--){
    		if(x[i] > y[i]) return 1;
    		if(x[i] < y[i]) return -1;
    	}
    	return 0;
    }
    
    void copy(int x[], int y[], int step){ //将y右移step位赋值给x,即 x = y * 10 ^ step
    	for(int i = 1; i <= y[0]; i++) x[i + step] = y[i];
    	x[0] = y[0] + step;
    }
    
    void sub(int x[], int y[]){ //模拟减法竖式运算
    	for(int i = 1; i <= x[0]; i++){
    		if(x[i] < y[i]){
    			x[i + 1]--;
    			x[i] += 10;
    		}
    		x[i] -= y[i];
    	}
    	while(!x[x[0]] && x[0]) x[0]--;
    }
    
    string _add(string x, string y){ //高精度加法
    	string res;
    	int nx[N] = {0}, ny[N] = {0}, ans[N + 1] = {0};
    	nx[0] = x.size(), ny[0] = y.size(), ans[0] = max(nx[0], ny[0]) + 1; //数组第0位存储长度
    	for(int i = nx[0]; i; i--) nx[i] = x[nx[0] - i] - '0'; //逆序存储
    	for(int i = ny[0]; i; i--) ny[i] = y[ny[0] - i] - '0';
    	for(int i = 1; i <= ans[0]; i++){ //模拟加法竖式运算
    		ans[i + 1] += (ans[i] + nx[i] + ny[i]) / 10;
    		ans[i] = (ans[i] + nx[i] + ny[i]) % 10;
    	}
    	while(!ans[ans[0]] && ans[0]) ans[0]--; //去除前导0
    	if(!ans[0]) return "0"; //如果长度为0直接返回0
    	for(int i = ans[0]; i; i--) res += ans[i] + '0'; //逆序回来并返回
    	return res;
    }
    
    string _minus(string x, string y){ //高精度减法
    	if(x.size() < y.size() || x.size() == y.size() && x < y) return "-" + _minus(y, x); //如果 x < y 返回 - (y - x)
    	string res;
    	int nx[N] = {0}, ny[N] = {0};
    	nx[0] = x.size(), ny[0] = y.size();
    	for(int i = nx[0]; i; i--) nx[i] = x[nx[0] - i] - '0';
    	for(int i = ny[0]; i; i--) ny[i] = y[ny[0] - i] - '0';
    	for(int i = 1; i <= nx[0]; i++){ //模拟减法竖式运算(可用上面sub函数代替)
    		if(nx[i] < ny[i]){
    			nx[i + 1]--;
    			nx[i] += 10;
    		}
    		nx[i] -= ny[i];
    	}
    	while(!nx[nx[0]] && nx[0]) nx[0]--;
    	if(!nx[0]) return "0";
    	for(int i = nx[0]; i; i--) res += nx[i] + '0';
    	return res;
    }
    
    string _mult(string x, string y){ //高精度乘法
    	string res;
    	int nx[N] = {0}, ny[N] = {0}, ans[N << 1] = {0};
    	nx[0] = x.size(), ny[0] = y.size(), ans[0] = nx[0] + ny[0];
    	for(int i = nx[0]; i; i--) nx[i] = x[nx[0] - i] - '0';
    	for(int i = ny[0]; i; i--) ny[i] = y[ny[0] - i] - '0';
    	for(int i = 1; i <= nx[0]; i++){ //模拟乘法竖式运算
    		for(int j = 1; j <= ny[0]; j++){
    			ans[i + j] += (ans[i + j - 1] + nx[i] * ny[j]) / 10;
    			ans[i + j - 1] = (ans[i + j - 1] + nx[i] * ny[j]) % 10;
    		}
    	}
    	while(!ans[ans[0]] && ans[0]) ans[0]--;
    	if(!ans[0]) return "0";
    	for(int i = ans[0]; i; i--) res += ans[i] + '0';
    	return res;
    }
    
    string _div(string x, string y){ //高精度除法
    	if(x.size() < y.size() || x.size() == y.size() && x < y) return "0"; //如果 x < y 返回 0
    	string res;
    	int nx[N] = {0}, ny[N] = {0}, ans[N] = {0};
    	nx[0] = x.size(), ny[0] = y.size(), ans[0] = nx[0] - ny[0] + 1;
    	for(int i = nx[0]; i; i--) nx[i] = x[nx[0] - i] - '0';
    	for(int i = ny[0]; i; i--) ny[i] = y[ny[0] - i] - '0';
    	for(int i = ans[0]; i; i--){ //模拟除法竖式运算
    		int temp[N] = {0};
    		copy(temp, ny, i - 1);
    		while(compare(nx, temp) >= 0){
    			sub(nx, temp);
    			ans[i]++;
    		}
    	}
    	while(!ans[ans[0]] && ans[0]) ans[0]--;
    	for(int i = ans[0]; i; i--) res += ans[i] + '0';
    	return res;
    }
    
    string _mod(string x, string y){ //高精度取余
    	if(x.size() < y.size() || x.size() == y.size() && x < y) return x; //如果 x < y 返回 x
    	string res;
    	int nx[N] = {0}, ny[N] = {0};
    	nx[0] = x.size(), ny[0] = y.size();
    	for(int i = nx[0]; i; i--) nx[i] = x[nx[0] - i] - '0';
    	for(int i = ny[0]; i; i--) ny[i] = y[ny[0] - i] - '0';
    	for(int i = nx[0] - ny[0] + 1; i; i--){ //模拟除法竖式运算
    		int temp[N] = {0};
    		copy(temp, ny, i - 1);
    		while(compare(nx, temp) >= 0){
    			sub(nx, temp);
    		}
    	}
    	if(!nx[0]) return "0";
    	for(int i = nx[0]; i; i--) res += nx[i] + '0';
    	return res;
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	cin >> a >> b;
    	cout << _add(a, b) << endl;
    	cout << _minus(a, b) << endl;
    	cout << _mult(a, b) << endl;
    	cout << _div(a, b) << endl;
    	cout << _mod(a, b) << endl;
    	return 0;
    }
    

    不过这道题为十六进制,所以需稍加改动

    #include <iostream>
    #define N 10010
    
    using namespace std;
    
    string a, b;
    
    string _add(string x, string y){
    	string res;
    	int nx[N] = {0}, ny[N] = {0}, ans[N + 1] = {0};
    	nx[0] = x.size(), ny[0] = y.size(), ans[0] = max(nx[0], ny[0]) + 1;
    	for(int i = nx[0]; i; i--){
            if(isdigit(x[nx[0] - i])) nx[i] = x[nx[0] - i] - '0';
            else nx[i] = x[nx[0] - i] - 'A' + 10;
        }
    	for(int i = ny[0]; i; i--){
            if(isdigit(y[ny[0] - i])) ny[i] = y[ny[0] - i] - '0';
            else ny[i] = y[ny[0] - i] - 'A' + 10;
        }
    	for(int i = 1; i <= ans[0]; i++){
    		ans[i + 1] += (ans[i] + nx[i] + ny[i]) / 16;
    		ans[i] = (ans[i] + nx[i] + ny[i]) % 16;
    	}
    	while(!ans[ans[0]] && ans[0]) ans[0]--;
    	if(!ans[0]) return "0";
    	for(int i = ans[0]; i; i--){
            if(ans[i] >= 0 && ans[i] <= 9) res += ans[i] + '0';
            else res += ans[i] + 'A' - 10;
        }
    	return res;
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	cin >> a >> b;
    	cout << _add(a, b) << endl;
    	return 0;
    }
    
    • 0
      @ 2023-7-18 16:22:03
      /*#include <iostream>
      using namespace std;
      const int Maxn=10;
      int a[Maxn],b[Maxn],c[2*Maxn];
      int lena, lenb, lenc, t;
      int main()
      {
          string s1,s2;
          cin>>s1>>s2;        //s1,s2为十进制字符串值,如:s1=(190)D, s2=(80)D
          lena=s1.length()-1; lenb=s2.length()-1; //lena: 数据a的最高权位,对应数值a实际存储下标:[0..lena]
          lenc=lena+lenb+1;                       //lenc: 相乘后的结果c[]位数是: lena+lenb+1, 也可能是: lena+lenb
          for(int i=0; i<=lena; i++){             //1. 将s1字符串转存入数组a[]中, 考虑到高位可以拓展, 因此最低位放在0位置
              if('0'<=s1[i] and s1[i]<='9') t=s1[i]-48;
              else t=s1[i]-'A'+10;
              a[lena-i]=t;
          }
          for(int i=0; i<=lenb; i++){
              if('0'<=s2[i] and s2[i]<='9') t=s2[i]-48;
              else t=s2[i]-'A'+10;
              b[lenb-i]=t;
          }
          for(int i=0; i<=lena; i++){             //2. 数据a与数据b按对应位置相乘, 权位i与权位j相乘, 其结果累加到数组c[i+j](权位:i+j)中
              for(int j=0; j<=lenb; j++){
                  c[i+j]=c[i+j]+a[i]*b[j];
              }
          }
          for(int i=0; i<=lenc; i++){             //3. 将相乘后的结果进行整理,整理成10进制
              c[i+1]+=c[i]/10;
              c[i]%=10;
          }
          while(c[lenc]==0 && lenc>0) lenc--;     //   最高位lenc值可能存在多个0, 将高位无效的0进行消除,(但要确保至少留下1位, 比如:乘以0)
          for(int i=lenc; i>=0; i--){             //4. 从高位到低位, 依次输出高精度数据c[lenc..0]
              printf("%d",c[i]);
          }
          return 0;
      }*/ //高精度乘法;
      
      
      
      
      /*#include <iostream>
      using namespace std;
      const int Maxn=10;
      int a[Maxn],b[Maxn],c[Maxn];
      int lena, lenb, lenc, t;
      int main()
      {
          string s1,s2;
          cin>>s1>>s2;        //s1,s2为十六进制字符串值,如:s1=(B90)H, s2=(80)H
          if(s1.length()<s2.length() or(s1.length()==s2.length() && s1<s2)){ //若s1数据小于s2数据, 则输出"-", 同时进行交换,s1与s2比较最高位字母或数字先后顺序,比较大小;
              cout<<"-";
              swap(s1,s2);
          }
          lena=s1.length()-1; lenb=s2.length()-1; //lena: 数据a的最高权位,对应数值a实际存储下标:[0..lena]
          lenc=lena;                 //lenc: 数据a大于数据b, a-b, 结果c最大可能权位<=lena
          for(int i=0; i<=lena; i++){             //1. 将s1字符串转存入数组a[]中, 考虑到高位可以拓展, 因此最低位放在0位置
              if('0'<=s1[i] and s1[i]<='9') t=s1[i]-48;
              else t=s1[i]-'A'+10;
              a[lena-i]=t;
          }
          for(int i=0; i<=lenb; i++){
              if('0'<=s2[i] and s2[i]<='9') t=s2[i]-48;
              else t=s2[i]-'A'+10;
              b[lenb-i]=t;
          }
          for(int i=0; i<=lenc; i++){             //2. 将数据a与数据b按对应位置相减
              c[i]=a[i]-b[i];
          }
          for(int i=0; i<=lenc; i++){             //3. 将各个位置数据, 从低位到高位, 依次整理成16进制数值(0..15)
              if(c[i]<0){c[i]+=16; c[i+1]--;}     //   整理负数
          }
          while(c[lenc]==0 && lenc>0) lenc--;     //   最高位lenc值可能存储多个0, 将高位无效的0进行消除,(但要确保至少留下1位)
          for(int i=lenc; i>=0; i--){             //4. 从高位到低位, 依次输出高精度数据c[lenc..0]
              if(c[i]>=10){printf("%c",c[i]+55);}
              else{printf("%d",c[i]);}
          }
          return 0;
      }*/ //高精度减法;
      
      
      #include <iostream>
      using namespace std;
      const int Maxn=100;
      int a[Maxn],b[Maxn],c[Maxn];
      int lena, lenb, lenc, t;
      int main()
      {
          string s1,s2;
          cin>>s1>>s2;        //s1,s2为十六进制字符串值,如:s1=(B90)H, s2=(80)H
          lena=s1.length()-1; lenb=s2.length()-1; //lena: 数据a的最高权位,对应数值a实际存储下标:[0..lena]
          lenc=max(lena, lenb)+1;                 //lenc: 数据a+b, 产生结果c的最大可能权位,实际也可能是lenc-1
          for(int i=0; i<=lena; i++){             //1. 将s1字符串转存入数组a[]中, 考虑到高位可以拓展, 因此最低位放在0位置
              if('0'<=s1[i] and s1[i]<='9') t=s1[i]-48;
              else t=s1[i]-'A'+10;
              a[lena-i]=t;
          }
          for(int i=0; i<=lenb; i++){
              if('0'<=s2[i] and s2[i]<='9') t=s2[i]-48;
              else t=s2[i]-'A'+10;
              b[lenb-i]=t;
          }
          for(int i=0; i<=lenc; i++){             //2. 将数据a与数据b按对应位置相加
              c[i]=a[i]+b[i];
          }
          for(int i=0; i<=lenc; i++){             //3. 将各个位置数据, 从低位到高位, 依次整理成16进制数值(0..15)
              c[i+1]+=c[i]/16;
              c[i]%=16;
          }
          if(c[lenc]==0) lenc--;                  //   最高位lenc值为0, 则不存在,进行退位
          for(int i=lenc; i>=0; i--){             //4. 从高位到低位, 依次输出高精度数据c[lenc..0]
              if(c[i]>=10){printf("%c",c[i]+55);}
              else{printf("%d",c[i]);}
          }
          return 0;
      }
      
      • 0
        @ 2023-7-18 16:13:56
        #include <iostream>
        using namespace std;
        const int Maxn=100;
        int a[Maxn],b[Maxn],c[Maxn];
        int lena, lenb, lenc, t;
        int main()
        {
            string s1,s2;
            cin>>s1>>s2;        //s1,s2为十六进制字符串值,如:s1=(B90)H, s2=(80)H
            lena=s1.length()-1; lenb=s2.length()-1; //lena: 数据a的最高权位,对应数值a实际存储下标:[0..lena]
            lenc=max(lena, lenb)+1;                 //lenc: 数据a+b, 产生结果c的最大可能权位,实际也可能是lenc-1
            for(int i=0; i<=lena; i++){             //1. 将s1字符串转存入数组a[]中, 考虑到高位可以拓展, 因此最低位放在0位置
                if('0'<=s1[i] and s1[i]<='9') t=s1[i]-48;
                else t=s1[i]-'A'+10;
                a[lena-i]=t;
            }
            for(int i=0; i<=lenb; i++){
                if('0'<=s2[i] and s2[i]<='9') t=s2[i]-48;
                else t=s2[i]-'A'+10;
                b[lenb-i]=t;
            }
            for(int i=0; i<=lenc; i++){             //2. 将数据a与数据b按对应位置相加
                c[i]=a[i]+b[i];
            }
            for(int i=0; i<=lenc; i++){             //3. 将各个位置数据, 从低位到高位, 依次整理成16进制数值(0..15)
                c[i+1]+=c[i]/16;
                c[i]%=16;
            }
            if(c[lenc]==0) lenc--;                  //   最高位lenc值为0, 则不存在,进行退位
            for(int i=lenc; i>=0; i--){             //4. 从高位到低位, 依次输出高精度数据c[lenc..0]
                if(c[i]>=10){printf("%c",c[i]+55);}
                else{printf("%d",c[i]);}
            }
            return 0;
        }
        
        • -1
          @ 2021-5-24 13:43:00

          C++ :

          #include <iostream>
          
          using namespace std;
          
          int main()
          {
              long long a,b,c;
              cin>>a>>b;
              c=a+b;
              cout<<c;
              return 0;
          }
          
          
        • 1

        【苏州NOI】d090: 高精度加法

        信息

        ID
        98
        时间
        1000ms
        内存
        128MiB
        难度
        7
        标签
        递交数
        311
        已通过
        65
        上传者