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


  如果我們需要很大范圍的十進制整數加法,對於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         else
140         {
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     }else
198         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 }

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM