码迷,mamicode.com
首页 > 其他好文 > 详细

7.2 大整数四则运算

时间:2016-07-19 20:26:00      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

7-2 BigInt1.c

  1 #include <stdio.h>
  2 #include <string.h>
  3 typedef struct bigint
  4 {
  5    char *num;                    //指向长整数数组(序号0中保存着最低位)
  6    char minus;                    //符号(1表示正数,-1表示负数) 
  7    int digit;                    //保存该数的位数(实际位数) 
  8 }BIGINT, *pBIGINT;
  9 void BigIntTrans(pBIGINT num);    //字符串转数字 
 10 void BigIntMul(pBIGINT num1, pBIGINT num2, pBIGINT result);    //乘法函数 
 11 void BigIntAdd1(pBIGINT num1, pBIGINT num2, pBIGINT result);    //同号数相加 
 12 void BigIntAdd(pBIGINT num1, pBIGINT num2, pBIGINT result);    //加法函数 
 13 void BigIntSub1(pBIGINT num1, pBIGINT num2, pBIGINT result);    //异号相减函数
 14 void BigIntSub(pBIGINT num1, pBIGINT num2, pBIGINT result);    //减法函数 
 15 void BigIntDiv(pBIGINT num1, pBIGINT num2, pBIGINT result, pBIGINT residue);    //除法函数 
 16 void BigIntPrint(pBIGINT result);    //输出大整数
 17 int BigIntEqual(pBIGINT num1, pBIGINT num2);    //两数大小比较
 18 
 19 void BigIntTrim(pBIGINT num1) //整理大整数,去掉前面多余的0,并使调整其位数
 20 {
 21    int i;
 22    for (i = num1->digit - 1; i >= 0; i--)
 23    {
 24       if (num1->num[i] != 0)
 25          break;
 26    }
 27    if (i < 0)    //若余数全部为0
 28    {
 29       num1->digit = 1;    //设置余数位数为1
 30       num1->num[0] = 0;
 31    } else
 32       num1->digit = i + 1;    //余数位数     
 33 }
 34 void BigIntTrans(pBIGINT num1) //将字符串转为数字表示
 35 {
 36    char *temp;                    //临时数组 
 37    int i, k, len;
 38    len = strlen(num1->num);    //字符串长度 
 39    if (!(temp = (char *) malloc(sizeof(char) * len)))    //分配内存 
 40    {
 41       printf("内存分配失败!\n");
 42       exit(0);
 43    }
 44    i = 0;
 45    num1->minus = 1;    //保存为正数 
 46    if (num1->num[0] == -)    //判断是否为负数 
 47    {
 48       num1->minus = -1;    //保存为负数 
 49       i++;
 50    }
 51    k = 0;    //数字位数计数器 
 52    while (num1->num[i] != \0)    //字符串未结束 
 53    {
 54       if (num1->num[i] >= 0 && num1->num[i] <= 9)    //为数字0~9 
 55       {
 56          temp[k] = num1->num[i] - 0;    //将ASCII码转换为对应数字 
 57          k++;
 58       }
 59       i++;
 60    }
 61 
 62    for (i = 0; i < num1->digit; i++)    //清空数组各元素 
 63       num1->num[i] = 0;
 64    num1->digit = k;    //转换后的数据位数 
 65    for (i = 0, k--; k >= 0; k--, i++)    //将临时数组各位反置保存到数组num中 
 66       num1->num[i] = temp[k];
 67    BigIntTrim(num1); //整理输入的大整数 
 68 }
 69 void BigIntPrint(pBIGINT result) //输出大整数 
 70 {
 71    int j;
 72    if (result->minus == -1)    //是负数 
 73       printf("-");    //输出负数 
 74    if (result->digit == 1 && result->num[0] == 0)    //若大整数为0
 75       printf("0");
 76    else //不为0 
 77    {
 78       for (j = result->digit - 1; j >= 0; j--) //从高位到低位输出 
 79          printf("%d", result->num[j]);
 80    }
 81 }
 82 int BigIntEqual(pBIGINT num1, pBIGINT num2) //比较绝对值大小
 83 {
 84    int i;
 85    if (num1->digit > num2->digit)    //num1的位数大于num2 
 86       return 1;
 87    else if (num1->digit < num2->digit)    //num1的位数小于num2
 88       return -1;
 89    else    //两数位数相等 
 90    {
 91       i = num1->digit - 1;    //num1的数据位数 
 92       while (i >= 0)    //从高位向低位比
 93       {
 94          if (num1->num[i] > num2->num[i])    //num1对应位大于num2
 95             return 1;
 96          else if (num1->num[i] < num2->num[i])    //num1对应位小于num2
 97             return -1;
 98          else
 99             i--; //比较下一位 
100       }
101    }
102    return 0;    //相等 
103 }
104 void BigIntAdd(pBIGINT num1, pBIGINT num2, pBIGINT result)
105 {
106    int i;
107    i = BigIntEqual(num1, num2);    //比较两数绝对值大小
108    if (i < 0)    //num1绝对值小于num2 
109    {
110      pBIGINT temp;
111      temp = num1;    //交换两数 
112      num1 = num2;
113      num2 = temp;
114    }
115    if (num1->minus * num2->minus < 0)    //符号不同,则执减法 
116    {      
117       if (i == 0)    //两数相等
118       {
119          result->digit = 1;    //结果长度为一位数,就是数值0
120          result->num[0] = 0;    //结果值为0
121          result->minus = 1;    //结果设为正号 
122          return;    //返回 
123       } 
124       BigIntSub1(num1, num2, result);    //调用相减函数完成异号相加的情况
125    } else
126       BigIntAdd1(num1, num2, result);    //调用相加函数完成同号相加
127 }
128 void BigIntAdd1(pBIGINT num1, pBIGINT num2, pBIGINT result)
129 {
130    int i, carry;
131    carry = 0;
132    result->minus = num1->minus;    //保存符号 
133    for (i = 0; i < num1->digit; i++)    //将被加数复制到结果数组中 
134       result->num[i] = num1->num[i];
135    for (i = 0; i < num2->digit; i++)    //num2中的数小,可能位数也小些
136    {
137       result->num[i] = result->num[i] + num2->num[i] + carry;    //将对应位的数和进位数相加 
138       carry = result->num[i] / 10;    //计算进位数据
139       result->num[i] = result->num[i] % 10;    //保留一位     
140    }
141    if (carry)    //若最后还有进位 
142       result->num[i] = result->num[i] + carry;
143    BigIntTrim(result);    //整理结果 
144 }
145 void BigIntSub1(pBIGINT num1, pBIGINT num2, pBIGINT result) //异号相减函数
146 {
147    int i, borrow;
148    result->minus = num1->minus;    //因num1绝对值比num2大,结果符号与num1相同 
149    borrow = 0;
150    for (i = 0; i < num1->digit; i++)    //将被减数的内容复制到结果中 
151       result->num[i] = num1->num[i];
152    for (i = 0; i <= num2->digit; i++)
153    {
154       result->num[i] = result->num[i] - num2->num[i] - borrow;    //num1减去num2,并减去低位的借位 
155       if (result->num[i] < 0)    //若为负数 
156       {
157          result->num[i] = 10 + result->num[i];    //向高位借位 
158          borrow = 1;    //设置借位值 
159       } else
160          borrow = 0;
161    }
162    if (borrow == 1)
163       result->num[i] = result->num[i] - borrow;
164    BigIntTrim(result);
165    /*i = num1->digit;
166    while (i > 0)
167    {
168       if (result->num[i] == 0)
169          i--;
170       else
171          break;
172    }
173    result->digit = i;    //保存结果位数*/
174 }
175 void BigIntSub(pBIGINT num1, pBIGINT num2, pBIGINT result) //减法函数 
176 {
177    num2->minus = -1 * num2->minus;    //将减数的符号取反 
178    BigIntAdd(num1, num2, result);    //调用加法函数 
179 }
180 void BigIntMul(pBIGINT num1, pBIGINT num2, pBIGINT result)
181 {
182    char carry, temp;
183    int i, j, pos;
184    for (i = 0; i < num1->digit + num2->digit; i++)    //结果数组和中间数组清0 
185       result->num[i] = 0;
186    for (i = 0; i < num2->digit; i++)    //用乘数的每1位乘以被乘数 
187    {
188       carry = 0;    //清除进位
189       for (j = 0; j < num1->digit; j++)    //被乘数的每1位 
190       {
191          temp = num2->num[i] * num1->num[j] + carry;    //相乘并加上进位
192          carry = temp / 10;    //计算进位carry
193          temp = temp % 10;    //计算当前位的值
194          pos = i + j;
195          result->num[pos] += temp;    //计算结果累加到临时数组中 
196          carry = carry + result->num[pos] / 10;    //计算进位 
197          result->num[pos] = result->num[pos] % 10;
198       }
199       if (carry > 0)
200       {
201          result->num[i + j] = carry;    //加上最高位进位
202          result->digit = i + j + 1;    //保存结果位数 
203       } else
204          result->digit = i + j;    //保存结果位数 
205    }
206    result->minus = num1->minus * num2->minus;    //结果的符号 
207 }
208 void BigIntDiv(pBIGINT num1, pBIGINT num2, pBIGINT result, pBIGINT residue) //除法函数函数 》?跞サ臀坏慕栉?雗um1相同 数
209 {
210    BIGINT quo1, residuo1, quo2;
211    int i, j, k, m;                //k保存试商结果,m保存商的位数 
212    char t;
213    result->minus = num1->minus * num2->minus;    //商的符号
214    residue->num = (char *) malloc(sizeof(char) * num2->digit);    //分配余数的内存空间
215    residue->digit = num2->digit+1;    //设置余数的初始位数与除数相同 
216    for (i = 0; i < residue->digit; i++)    //将余数全部清0 
217       residue->num[i] = 0;
218    m = 0;
219    for (i = num1->digit - 1; i >= 0; i--)
220    {
221       residue->digit=num2->digit+1; //重新设置余数的位数比除数多一位 
222       for (j = residue->digit - 1; j > 0; j--)    //移余数 
223          residue->num[j] = residue->num[j - 1];    //将序号低位的数据移向高位(实际是将余数中的最高位去除) 
224       residue->num[0] = num1->num[i];    //复制被除数中的一位到余数的最低位中 
225       BigIntTrim(residue);//整理余数 
226       k = 0;    //试商
227       while (BigIntEqual(residue, num2) >= 0)    //比较余数与除数的大小
228       {
229          BigIntSub1(residue, num2, residue);    //用余数减去除数,差值保存在余数中
230          k++;    //试商加1 
231       }
232       result->num[m++] = k;    //保存商    
233    }
234    result->digit = m;    //保存商的位数 
235    for (i = 0; i < m / 2; i++)    //将商各位反转(在计算过程中序号0保存的是商的高位) 
236    {
237       t = result->num[i];
238       result->num[i] = result->num[m - 1 - i];
239       result->num[m - 1 - i] = t;
240    }
241    BigIntTrim(result);    //整理商 
242    BigIntTrim(residue);    //整理余数 
243 }
244 int main()
245 {
246    BIGINT num1, num2, result, residue;    //参与运算的数、结果、余数 
247    int i = 0, len;
248    char op;
249    printf("输入最大数的位数:");
250    scanf("%d", &len);
251    if (!(num1.num = (char *) malloc(sizeof(char) * (len + 1))))
252    {
253       printf("内存分配失败!\n");
254       exit(0);
255    }
256    num1.digit = len + 1;
257    if (!(num2.num = (char *) malloc(sizeof(char) * (len + 1))))
258    {
259       printf("内存分配失败!\n");
260       exit(0);
261    }
262    num2.digit = len + 1;
263    if (!(result.num = (char *) malloc(sizeof(char) * (2 * len + 1))))
264    {
265       printf("内存分配失败!\n");
266       exit(0);
267    }
268    result.digit = 2 * len + 1;
269    for (i = 0; i < result.digit; i++)    //清空结果集 
270       result.num[i] = 0;
271    printf("选择大整数的运算(+、-、*、/):");
272    fflush(stdin);
273    scanf("%c", &op);
274    switch (op)
275    {
276    case +:
277       printf("\n输入被加数:");
278       scanf("%s", num1.num);
279       printf("\n输入加数:");
280       scanf("%s", num2.num);
281       BigIntTrans(&num1);
282       BigIntTrans(&num2);
283       BigIntAdd(&num1, &num2, &result);    //加法 
284       break;
285    case -:
286       printf("\n输入被减数:");
287       scanf("%s", num1.num);
288       printf("\n输入减数:");
289       scanf("%s", num2.num);
290       BigIntTrans(&num1);
291       BigIntTrans(&num2);
292       BigIntSub(&num1, &num2, &result);    //减法 
293       break;
294    case *:
295       printf("\n输入被乘数:");
296       scanf("%s", num1.num);
297       printf("\n输入乘数:");
298       scanf("%s", num2.num);
299       BigIntTrans(&num1);
300       BigIntTrans(&num2);
301       BigIntMul(&num1, &num2, &result);    //乘法 
302       break;
303    case /:
304       printf("\n输入被除数:");
305       scanf("%s", num1.num);
306       printf("\n输入除数:");
307       scanf("%s", num2.num);
308       BigIntTrans(&num1);
309       BigIntTrans(&num2);
310       if (num2.digit == 1 && num2.num[0] == 0)    //大整数为0
311          printf("除数不能为0!\n");
312       else
313          BigIntDiv(&num1, &num2, &result, &residue);    //除法法 
314       break;
315    }
316    if (op == /)
317    {
318       if (!(num2.digit == 1 && num2.num[0] == 0))    //为除法且除数不为0
319       {
320          printf("商:");
321          BigIntPrint(&result);
322          printf("\t余数:");
323          BigIntPrint(&residue);
324       }
325    } else
326    {
327       printf("\n结果:");
328       BigIntPrint(&result);
329    }
330 
331    getch();
332    return 0;
333 }

 

7.2 大整数四则运算

标签:

原文地址:http://www.cnblogs.com/wozixiaoyao/p/5686007.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!