• 高精度


     这里写了关于高精度的加减乘除运算,前面三种都可用我们平时列式子,打草稿的思维写出来,对位相加,对位相减,错位相乘。但是除法就需要注意了,它的商很不好计算,不信的可以自己想一下思路再看下面,具体的除法思路在下面代码的注释中

      1 #include"iostream"
      2 #include"string"
      3 using namespace std;
      4 string add(string s1,string s2);
      5 string operator- (string s1,string s2);
      6 string operator* (string s1,string s2);
      7 string operator/ (string s1,string s2);
      8 void check(string &s);
      9 int compare(string &s1,string &s2);
     10 
     11 void check(string &s){          //去除前面多余的0
     12     string s1 = "";
     13     int i = 0;
     14     while(s[i++] == '0');
     15     i--;
     16     while(s[i] != 0){
     17         s1 += s[i++];
     18     }
     19     s = (s1 == "" ? "0" : s1);
     20 }
     21 
     22 int compare(string &s1,string &s2){     //比较两个数
     23     int len1 = s1.length();
     24     int len2 = s2.length();
     25     if(len1 > len2){
     26         return 1;
     27     }
     28     else if(len1 < len2){
     29         return -1;
     30     }
     31     else if(s1 > s2){
     32         return 1;
     33     }
     34     else if(s1 < s2){
     35         return -1;
     36     }
     37     else{
     38         return 0;
     39     }
     40 }
     41 string add(string s1,string s2){           //为了不影响+连接字符串,这里不重载+号运算符
     42     if(s1[0] == '-'){                    //第一个数为负,当作第二个数减第一个,这时不用判断另一个数是否为负,因为减法已经有处理负数的能力
     43         string s3(&s1[1]);
     44         return s2 - s3;
     45     }
     46     if(s2[0] == '-'){                       //第二个数为负,当作第一个数减第二个
     47         string s3(&s2[1]);
     48         return s1 - s3;
     49     }
     50     int len1 = s1.length();
     51     int len2 = s2.length();
     52     int i = len1 - 1,j = len2 - 1,k = 0;
     53     char c[10000] = {0};
     54     while(i >= 0 && j >= 0){        //从末尾开始对应相加
     55         c[k++] = s1[i--] - '0' + s2[j--] - '0';
     56     }
     57     while(i >= 0){                  //加上剩下的s1
     58         c[k++] = s1[i--] - '0';
     59     }
     60     while(j >= 0){                   //加上剩下的s2
     61          c[k++] =  s2[j--] - '0';
     62     }
     63     c[k] = 0;           //末尾标记
     64     for(int i = 0;i <= k;i++){    //进位
     65         if(c[i] > 9){
     66             c[i] -= 10;
     67             c[i + 1]++;
     68         }
     69     }
     70     for(int i = 0;i <= k;i++){      //转换为asc字符
     71         c[i] += '0';
     72     }
     73     string s3(c);       //用c创建string
     74     string s4(s3.rbegin(),s3.rend());   //再逆序创建
     75     check(s4);      //去首位的0
     76     return s4;
     77 }
     78 string operator- (string s1,string s2){
     79     int isfushu = 0;
     80     if(s1[0] == '-' && s2[0] != '-'){       //被减数为负数,相当于加法
     81         string s3(s1.begin() + 1,s1.end());
     82         return "-" + add(s3,s2);
     83     }
     84     if(s2[0] == '-' && s1[0] != '-'){       //减数为负,也相当于加法
     85         string s3(s2.begin() + 1,s2.end());
     86         return add(s3,s1);
     87     }
     88     if(s2[0] == '-' && s1[0] == '-'){       //都为负,相当于是减数与被减数交换位置
     89         string s3(s1.begin() + 1,s1.end());
     90         string s4(s2.begin() + 1,s2.end());
     91         s1 = s4;
     92         s2 = s3;
     93     }
     94     if(compare(s1,s2) < 0){     //如果s1 < s2 交换位置,并标记为负数
     95         isfushu = 1;
     96         string s3 = s1;
     97         s1 = s2;
     98         s2 = s3;
     99     }
    100     int len1 = s1.length();
    101     int len2 = s2.length();
    102     int i = len1 - 1,j = len2 - 1;
    103     while(i >= 0 && j >= 0){        //从末尾开始对应相减
    104         s1[i--] -= (s2[j--] - '0');
    105     }
    106     for(int i = len1 - 1;i > 0;i--){    //借位
    107         if(s1[i] < '0'){
    108             s1[i - 1]--;
    109             s1[i] += 10;
    110         }
    111     }
    112     check(s1);
    113     if(isfushu){            //负数前面加上负号
    114         s1 = "-" + s1;
    115     }
    116     return s1;
    117 }
    118 
    119 string operator* (string s1,string s2){
    120     int isfushu = 0;
    121     if(s1[0] == '-' && s2[0] != '-') {      //有一个为负数则为负数
    122         isfushu = 1;
    123         s1 = string(&s1[1]);
    124     }
    125     if(s2[0] == '-' && s1[0] != '-'){
    126         isfushu = 1;
    127         s2 = string(&s2[1]);
    128     }
    129     if(s2[0] == '-' && s1[0] == '-'){       //全为负数,结果为正
    130         s1 = string(&s1[1]);
    131         s2 = string(&s2[1]);
    132     }
    133     int len1 = s1.length();
    134     int len2 = s2.length();
    135     char c[10000] = {0};        //临时数组
    136     for(int i = len1 - 1;i >= 0;i--){   //从最低位开始计算
    137         for(int j = len2 - 1;j >= 0;j--){
    138             int ge = (s1[i] - 48) * (s2[j] - 48);   //两位相乘结果
    139             int gew = len1 + len2 - i - j - 2;      //当前个位的下标
    140             c[gew] += ge % 10;              //加上个位
    141             c[gew + 1] += ge / 10 % 10;      //加上十位
    142         }
    143         int k = 0;
    144         while(k < len1 + len2 - 1){         //进位,每一位数乘完每一个数后就进位,char最大为127,这里最大为9+9+9=27,保证了在最大值内,不会出错
    145             //cout<<(int)c[k]<<endl;
    146             c[k + 1] += (c[k] / 10);
    147             c[k] = c[k] % 10;
    148             ++k;
    149         }
    150     }
    151     //char 型数组的进位不能放这里,int 型数组可以
    152     for(int i = 0;i < len1 + len2;i++){       //转换为asc字符
    153         c[i] += 48;
    154     }
    155     string s3(c);
    156     string s4(s3.rbegin(),s3.rend());
    157     check(s4);
    158     if(isfushu){
    159         return "-" + s4;
    160     }
    161     return s4;   //返回逆序
    162 }
    163 
    164 int jianfa(string &s1,string &s2){      //用于除法的减法,通过减的次数来求商,这个减法不能当作一般的减法使用
    165     int len1 = s1.length();
    166     int len2 = s2.length();
    167     int i,j,count = 0;
    168     while(true){
    169         i = len1 - 1;
    170         j = len2 - 1;
    171         string temp = s1;       //临时保存被减数
    172         while(i >= 0 && j >= 0){        //从末尾开始对应相减
    173             s1[i--] -= (s2[j--] - '0');
    174         }
    175         for(int i = len1 - 1;i > 0;i--){    //借位
    176             if(s1[i] < '0'){
    177                 s1[i - 1]--;
    178                 s1[i] += 10;
    179             }
    180         }
    181         if(s1[0] < '0'){    //首位都被借完了,停止相减,并恢复被减数
    182             s1 = temp;
    183             break;
    184         }
    185 
    186         count++;
    187     }
    188     return count;
    189 }
    190 
    191 string operator/ (string s1,string s2){
    192     int jianfa(string &s1,string &s2);
    193     int isfushu = 0;
    194     if(s1[0] == '-' && s2[0] != '-') {      //有一个为负数则为负数
    195         isfushu = 1;
    196         s1 = string(&s1[1]);
    197     }
    198     if(s2[0] == '-' && s1[0] != '-'){
    199         isfushu = 1;
    200         s2 = string(&s2[1]);
    201     }
    202     if(s2[0] == '-' && s1[0] == '-'){       //全为负数,结果为正
    203         s1 = string(&s1[1]);
    204         s2 = string(&s2[1]);
    205     }
    206     int len1 = s1.length();
    207     int len2 = s2.length();
    208     char chushu[10000] = {0};           //临时保存除数,这里的除数是指扩大10*n倍后的除数.
    209     string s4 = "";                 //保存结果
    210     for(int i = len1 - 1;i >= len2 - 1;i--){       //这里i表示除数的位数,它的位数在len2~~~len1之间,如12345/45,那么除数分别为45000,4500,450,45
    211         for(int j = 0;j <= i;j++){              //修改除数
    212             if(j < len2){
    213                 chushu[j] = s2[j];      //先存上本身除数
    214             }
    215             else{
    216                 chushu[j] = '0';        //后面的用0填充
    217             }
    218         }
    219         chushu[i + 1] = 0;      //结束标志
    220         string s3(chushu);      //转为string
    221         s4 += jianfa(s1,s3) + 48;   //被除数 - 除数,直到不够减为止,减的次数就是该位的商,如125/5:125-500=0次,125-50=2次,25-5=5次,结束,那么商为25
    222     }
    223     check(s1);      //余数
    224     check(s4);      //
    225     if(isfushu){
    226         if(s1[0] != '0'){
    227             s1 = '-' + s1;
    228         }
    229         if(s4[0] != '0'){
    230             s4 = '-' + s4;
    231         }
    232     }
    233     //cout<<"余数:"<<s1<<endl;
    234     return s4;
    235 }
    236 
    237 int main(){
    238     string s1,s2;
    239     //cout<<add(s1,s2)<<endl;
    240     cin>>s1>>s2;
    241     cout<<add(s1,s2)<<endl;
    242     cout<<s1 - s2<<endl;
    243     cout<<s1 * s2<<endl;
    244     cout<<s1 / s2<<endl;
    245     return 0;
    246 }
  • 相关阅读:
    简易表格练习
    CSS圆角样式
    力不从心
    学渣在努力~
    嫌疑人
    poj1308 Is it a tree?
    悲剧文本
    迷宫问题
    n皇后问题
    油田
  • 原文地址:https://www.cnblogs.com/oleolema/p/9181039.html
Copyright © 2020-2023  润新知