7.2 大整数四则运算

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 }
时间: 2024-08-10 07:13:51

7.2 大整数四则运算的相关文章

大整数四则运算(vector)

目录 基础 1. 高精度加法 2. 高精度减法 3. 高精度乘低精度 4. 高精度除以低精度 5. 高精度乘高精度 6. 高精度除以高精度 综合 总结 每逢大整数四则运算,都会怯懦,虽是算法竞赛必会的东西,也零散的学过,简单的总结过,但不成体系的东西心里一直没底. 所以今天消耗了大量的卡路里,啃了几套模板之后终于总结成了一套自己的模板 再也不用担心大整数啦 基础 1. 高精度加法 高精度加法等同于算术加法,做单个的加法运算之后存下进位 A和B都为正整数 vector中下标为0存的是低位(以下都是

大整数四则运算

============ 日后再写!先将设计思想留下 ============= 定义并实现超长整数类double long,要求如下: 64位数据长度,有符号 支持+.-.*./运算 支持+=.-=./=运算 支持cin>>和cout<<操作 首先,我们的运算对象是大整数并且要支持cout<<和cin>>操作,数组和链表是可选择项.在这里我们用数组.数组有int型和char型,选哪个好呢?只能选char型,因为我们的大整数是有符号位的,必须用一个char字

【面试】大整数四则运算

面试手写代码,当时只写出了加减乘,还写的漏洞百出.下面是加减法: 1 #include<iostream> 2 using namespace std; 3 4 struct BigN { 5 int data[1000]; //设最长1000位,数组的每个数字代表一位,data[0]存最低位 6 int len; 7 int sign;//0为负,1为正 8 BigN() { 9 memset(data, 0, sizeof(data)); 10 len = 0; 11 sign = 1;

模板 高精度大整数

#include<bits/stdc++.h> #define clr(x,y) memset((x),(y),sizeof(x)) using namespace std; typedef long long LL; const int MaxL=400; //大数长度 //大整数 //减法只能大减小 struct bign { int len, s[MaxL]; //构造函数 bign () { memset(s, 0, sizeof(s)); len = 1; } bign (int n

大整数的存储与加减乘除四则运算

当需要计算的整数或计算结果可能会超出long long 所能表示的范围时,应该用大整数来存储和计算(Java里面有BigInteger来存储大整数,这里讨论的是C++语言). 大整数的存储形式是下面这个结构体(包含了构造函数): // 大整数结构体 struct bign{ int d[1000]; int len; bign(){ memset(d, 0, sizeof(d)); len = 0; } }; 首先以字符串的形式读去数据,然后将字符串逐个逆序字符存入d[]数组(可以采用用reve

大整数类

大整数类又叫高精度. 就是求大数的四则运算的算法, (其实就是模拟小学生算数的方法, 什么? 你不会, 那你还不如小学生, 哈哈!). 在这里只贴加法运算符的重载,其他的运算符与加法类似.闲言少叙, 直接上代码(小声告诉你, 里面用了几个库函数和STL, 嘿嘿!!!). 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<iostream> 5 using namespac

大整数的加减乘除

多项式的加减乘除能够利用多项式的加减乘除进行运算,所以下面程序採用了多项式的加减乘除.多项式运算已经在<算法导论>第30章有简要的介绍,详细的请參考数学书. 大整数加法:(利用书上公式轻松得出) //多项式加法-大数加法 #include <iostream> #include <time.h> using namespace std; #define m1 4 #define m2 5 //a[0]=x^0 a[1]=x^1....a[n]=x^n的关于x的多项式系数

大整数类BIGN的设计与实现 C++高精度模板

首先感谢刘汝佳所著的<算法竞赛入门经典>. 众所周知,C++中储存能力最大的unsigned long long 也是有着一个上限,如果我们想计算非常大的整数时,就不知所措了,所以,我写了一个高精度类,允许大整数的四则运算 这个类利用字符串进行输入输出,并利用数组进行储存与处理,通过模拟四则运算,可以计算很大的整数的加减乘除比大小. 贴上我的代码: #include<string> #include<iostream> #include<iosfwd> #i

大整数运算C++1

//下面的代码勉强算是bignum_beta1版本! //实现了大整数的加减乘除四则运算,以及求两个整数的最大公约数,以及求乘法逆,miller_rabin素性检验,平方_乘法算法 //不足之处,位数还很难扩展至几千位,以及运算速度有一点慢,既然是beta1,说明bug还是挺多的 //程序缺少测试数据来测试,所以有的结果不敢保证其正确性 //由于使用c++复写了很多运算符,加入这个文件之后,大数bignum可以看做是一个如同如同int一样的基本类型 //可以像int一样加减乘除和输入输出 #in