C语言实现大数四则运算

时间:2021-06-30 20:41:06

一、简介

众所周知,C语言中INT类型是有限制,不能进行超过其范围的运算,而如果采用float类型进行运算,由于float在内存中特殊的存储形式,又失去了计算的进度。要解决整个问题,一种解决方法是通过字符串数组实现数据的存储,然后实现它们之间四则运算的函数。

二、数据结构

为了实现字符数组之间的运算,要考虑数值的正负性,数字的长度以及具体存储的数字

typedef struct num{
int len; //数值长度
char symbol; //数字正负形
int number[LEN]; //数组
}NUM,*SNUM;

三、函数

 整个程序使用了一下的函数

SNUM expToNum(char exp[]);//将输入字符串转换为对应结构体 
void reverse(int a[],int len);//数组逆序
int compareAbs(SNUM left,SNUM right);//比较两数绝对值大小
SNUM anti_add(SNUM left,SNUM right);//元加法
SNUM anti_sub(SNUM left,SNUM right);//元减法
SNUM add(SNUM left,SNUM right); //加法
SNUM sub(SNUM left,SNUM right); //减法
SNUM multiply(SNUM left,SNUM right); //乘法
SNUM divide(SNUM left,SNUM right); //除法
SNUM mod(SNUM left,SNUM right);//求摸运算

函数的定义

  1 SNUM multiply(SNUM left,SNUM right){
2 //left作为被乘数,right作为乘数
3 SNUM mul = (struct num*)malloc(sizeof(struct num));
4 int i,j;
5 for(i=0;i<LEN;i++){
6 mul->number[i]=0;
7 }
8
9 if(left->symbol==right->symbol){
10 mul->symbol='+';
11 }else{
12 mul->symbol='-';
13 }
14
15
16
17 for(i=0;i<right->len;i++){
18 for(j=0;j<left->len;j++){
19 mul->number[i+j]+=left->number[j]*right->number[i];
20 }
21 }
22
23
24
25 // //进位化简
26 int len = left->len+right->len-1; //长度
27
28 //
29 for(i=0;i<len;i++){
30 mul->number[i+1]+=mul->number[i]/10;
31 mul->number[i]%=10;
32
33 if(i==len-1){
34 if(mul->number[i+1]!=0){ //还存在高位
35 len++;
36 }else{ //进位完毕,退出
37 break;
38 }
39 }
40 }
41
42
43
44 // //舍去多余0位
45 for(i=len-1;i>=0;i--){
46 if(mul->number[i]==0){
47 len--;
48 }else{
49 break;
50 }
51 }
52 if(len==0){
53 len=1;
54 }
55
56 mul->len=len;
57
58 free(left);
59 free(right);
60 return mul;
61 }
62
63
64
65 //减一个数等于加上一个数的相反数
66 SNUM sub(SNUM left,SNUM right){
67 right->symbol=(right->symbol=='+'?'-':'+');
68 return add(left,right);
69 }
70
71 //比较两数绝对值大小
72 int compareAbs(SNUM left,SNUM right){
73 if(left->len>right->len){ //left的位数更多
74 return 1;
75 }else if(left->len<right->len){ //right的位数更多
76 return -1;
77 }else{
78 int i=left->len-1;
79 while(i>=0){ //从高位开始比较
80 if(left->number[i]>right->number[i]){
81 return 1;
82 }
83 if(left->number[i]<right->number[i]){
84 return -1;
85 }
86 i--;
87 }
88 return 0; //两者绝对值相等
89 }
90 }
91
92
93 SNUM expToNum(char exp[]){
94
95 SNUM temp=(struct num*)malloc(sizeof(struct num));
96
97 int locan=0;
98 //确定正负号
99 if(exp[0]=='+'||exp[0]=='-'){
100 temp->symbol=exp[0];
101 locan++;
102 }else{
103 temp->symbol='+';
104 }
105
106 //输入到数组
107 int count=0;
108 while(exp[locan]!='\0'){
109 temp->number[count]=exp[locan]-'0';
110 locan++;
111 count++;
112 }
113
114 int i=count;
115 for(i=count;i<LEN-1;i++){
116 temp->number[i]=0;
117 }
118
119 temp->len=count;
120
121
122 //数组逆序从个位开始计算
123 reverse(temp->number,temp->len);
124
125 return temp;
126 }
127
128 //数组逆序
129 void reverse(int a[],int len){
130 int i,temp;
131 for(i=0;i<len/2;i++){
132 temp = a[i];
133 a[i] = a[len-1-i];
134 a[len-1-i] = temp;
135 }
136 }
137
138
139
140 //元加法,假设left和right都为正数或0
141 SNUM anti_add(SNUM left,SNUM right){
142 int i=0;
143
144 while(i<left->len||i<right->len){
145 int sum=0;
146 sum=left->number[i]+right->number[i];
147 if(sum>=10){
148 left->number[i]=sum%10;
149 left->number[i+1]+=sum/10; //进位
150 }else{
151 left->number[i]=sum; //不进位
152 }
153
154 i++;
155 }
156
157 if(left->number[i]!=0){
158 i+=1;
159 }
160
161 left->len=i;
162 return left;
163 }
164
165 //实现正数或负数的加法
166 SNUM add(SNUM left,SNUM right){
167 SNUM temp;
168 if(left->symbol==right->symbol){
169 temp = anti_add(left,right);
170 }else{
171 if(compareAbs(left,right)>=0){
172 temp = anti_sub(left,right);
173
174 }else{
175 temp = anti_sub(right,left);
176 }
177 }
178 return temp;
179 }
180
181 //元减法,假设left>=right,left和right均为正数或0
182 SNUM anti_sub(SNUM left,SNUM right){
183 int i=0;
184 int count=0;
185 while(i<left->len){
186 int temp = left->number[i]-right->number[i];
187 if(temp<0){
188 left->number[i+1]-=1;
189 left->number[i]=temp+10; //退位
190 }else{
191 left->number[i]=temp;
192 }
193
194 count+=1;
195
196 i++;
197 }
198
199
200
201
202 //舍掉多余的0
203 for(i=count-1;i>=0;i--){
204 if(left->number[i]==0){
205 count--;
206 }else{
207 break;
208 }
209 }
210
211 if(count==0){
212 count++;
213 }
214
215 left->len=count;
216 return left;
217
218 }