高精度整数加法(大整数加法)

来源:互联网 发布:剑三长歌成女捏脸数据 编辑:程序博客网 时间:2024/05/16 17:20

  如果我们需要很大范围的十进制整数加法,对于4字节int型,不能表示该数据,此时需要用字符串保存操作数和结果,采取逐位运算的方式。如:

  987654321 + 1234567989 = 1111111110

  -1234 + (-4567) = -5801

  -1234 + 30 = -1204

  0 + 0 = 0

  0 + 34 = 34.

  实现函数void add(const char *num1, const char *num2, char *result).

  注:输入字符串所有位均为有效数字,不存在由0开始的串。要求输出所有位也是有效数组。

    正数前没有符号,负数在最开始有 ‘-’号。

 实现如下:

  开始以为分分钟搞定,结果写了几个小时,有很多细节要考虑:如(1)做减法时去掉符号后,要保证用大的数减去小的数;(2)逐为累加时要考虑哪个数长,把多余部分与进位相加,另外有可能两个数都完了,但是此时还有进位不为0。

  因为是用C写的,因为题目给出了函数的签名,所以代码写了很长,因为对字符串的各种处理都要自己手动进行。

复制代码
  1 #include<stdio.h>  2 #include<stdlib.h>  3 #include<string.h>  4   5 void move(char *str, int length)    //移除字母前的"-"符号  6 {  7     if(str[0] != '-')  8         return;  9     int i; 10     for(i = 0; i < length-1; i++) 11         str[i] = str[i+1]; 12     str[i] = '\0'; 13 } 14  15 int remove_zero(char *result, int length) 16 { 17     int count = 0; 18     for(int i = length-1; i > 0; i--)    //从最后开始移除0,直到遇到非0数字,只对最初位置上的0不予判断 19     { 20         if(result[i] == '0') 21         { 22             result[i] = '\0'; 23             count++; 24         }else 25             return length-count; 26     } 27     return length - count; 28 } 29  30 void reverse(char *result, int length)        //将字符串倒转 31 { 32     char temp; 33     for(int i = 0; i <= (length-1)/2; i++) 34     { 35         temp = result[i]; 36         result[i] = result[length-1-i]; 37         result[length-1-i] = temp; 38     } 39 } 40  41 int real_add(char *str1, char *str2, char *result, const bool flag) 42 { 43     int len1 = strlen(str1); 44     int len2 = strlen(str2); 45     int n1, n2, another = 0;    //another表示进位 46     int cur_rs = 0;        //表示result的当前位数 47     int i, j; 48     int curSum; 49     for(i = len1-1, j = len2-1; i >= 0 && j >= 0; i--, j--) 50     { 51         n1 = str1[i] - '0'; 52         n2 = str2[j] - '0'; 53         curSum = n1 + n2 + another; 54         result[cur_rs++] = curSum % 10 + '0'; 55         another = curSum / 10; 56     } 57  58     if(j < 0) 59     { 60         while(i >= 0)        //遍历str1剩余各位 61         { 62             n1 = str1[i--] - '0'; 63             curSum = n1 + another; 64             result[cur_rs++] = curSum % 10 + '0'; 65             another = curSum / 10; 66         } 67         if(another != 0)        //如果还有进位未加上 68             result[cur_rs++] = another + '0'; 69     }else{ 70         while(j >= 0) 71         { 72             n2 = str2[j--] - '0'; 73             curSum = n2 + another; 74             result[cur_rs++] = curSum % 10 + '0'; 75             another = curSum / 10; 76         } 77         if(another != 0) 78             result[cur_rs++] = another + '0'; 79     } 80  81     result[cur_rs] = '\0'; 82  83     cur_rs = remove_zero(result, cur_rs); 84     if(!flag) 85     { 86         result[cur_rs++] = '-'; 87         result[cur_rs] = '\0'; 88     } 89     reverse(result, strlen(result)); 90     return cur_rs; 91 } 92  93  94 int real_minus(char *str1, char *str2, char *result)    //使用str1减去str2 95 { 96     char big[100], small[100]; 97     int big_len, sml_len; 98  99     int len1 = strlen(str1);100     int len2 = strlen(str2);101     bool flag = false;        //用于标记str2是否比str1大102 103     if(len1 < len2)104         flag = true;105     else if(len1 == len2)106     {107         if(strcmp(str1, str2) == 0)108         {109             result[0] = '0';110             result[1] = '\0';111             return 1;112         }else if(strcmp(str1,str2) < 0)113             flag = true;114     }115 116     if(flag)    //将str1和str2交换,确保str1指向的值是其中较大者,最后通过flag确定要不要给前面加-号117     {118         char *temp = str1;119         str1 = str2;120         str2 = temp;121         len1 = strlen(str1);122         len2 = strlen(str2);123     }124 125     int n1, n2, another = 0;    //another表示是否有借位126     int i, j;127     int cur_rs = 0;128     int curMinus;129 130     for(i = len1-1, j = len2-1; i>=0 && j>=0; i--,j--)131     {132         n1 = str1[i] - '0';133         n2 = str2[j] - '0';134         if(n1 >= n2+another)135         {136             result[cur_rs++] = (n1-n2-another) +'0';137             another = 0;138         }139         else140         {141             result[cur_rs++] = (n1+10-n2-another) + '0';142             another = 1;143         }144     }145 146     while(i >= 0)147     {148         n1 = str1[i--] - '0';149         if(another != 0)150         {151             n1 -= another;152             another = 0;153         }154         result[cur_rs++] = n1 + '0';155     }156     157     result[cur_rs] = '\0';158     cur_rs = remove_zero(result, cur_rs);159     if(flag)160     {161         result[cur_rs++] = '-';162         result[cur_rs] = '\0';163     }164     reverse(result, cur_rs);165 166     return cur_rs;167 }168 169 void add(const char *num1, const char *num2, char *result)170 {171     int len1 = strlen(num1);172     int len2 = strlen(num2);173     int rs_len;174     if(!len1 || !len2)175             return;176     char str1[100], str2[100];177     strncpy(str1, num1, len1);178     str1[len1] = '\0';179     strncpy(str2, num2, len2);180     str2[len2] = '\0';181 182     if(str1[0] == '-' && str2[0] == '-')183     {184         move(str1, len1);185         move(str2, len2);186         rs_len = real_add(str1, str2, result, false);187 188     }else if(str1[0] == '-')189     {190         move(str1, len1);191         rs_len = real_minus(str2, str1, result);192     }193     else if(str2[0] == '-')194     {195         move(str2, len2);196         rs_len = real_minus(str1, str2, result);197     }else198         rs_len = real_add(str1, str2, result, true);199 }200 201 int main(int argc, char *argv[])202 {203     char result[100];204     memset(result, 0, 100);205     add(argv[1], argv[2], result);206     printf("%s\n", result);207 208     return 0;209 }
复制代码
原创粉丝点击