1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 typedef struct bigInt { 6 char* num;//指向长整数数组,序号0中保存着最低位,也就是倒序存放 7 char minus;//符号,1表示正数,-1表示符数 8 int digit;//保存位数 9 }BigInt, *pBigInt; 10 11 void bigIntTrans(pBigInt num1);//将字符串转化成数字表示 12 void bigIntTrim(pBigInt num1);//整理大整数,去掉前面得0 13 void bigIntPrint(pBigInt result); 14 int bigIntEqual(pBigInt num1, pBigInt num2);//比较两个大整数大小 15 void bigIntAdd(pBigInt num1, pBigInt num2, pBigInt result); 16 void bigIntAdd1(pBigInt num1, pBigInt num2, pBigInt result);//同号相加 17 void bigIntSub1(pBigInt num1, pBigInt num2, pBigInt result);//用于异号相加 18 void bigIntSub(pBigInt num1, pBigInt num2, pBigInt result);//减法 19 void bigIntMul(pBigInt num1, pBigInt num2, pBigInt result);//乘法 20 void bigIntDiv(pBigInt num1, pBigInt num2, pBigInt result, pBigInt residue);//除法 21 22 int main(void) { 23 bigInt num1, num2, result, residue; 24 int i = 0, len; 25 char op; 26 27 printf("输入最大数的位数:"); 28 scanf("%d", &len); 29 if (!(num1.num = (char*)malloc(sizeof(char) * (len + 1)))) { printf("内存分配失败\n"); exit(0); } 30 num1.digit = len + 1; 31 if (!(num2.num = (char*)malloc(sizeof(char) * (len + 1)))) { printf("内存分配失败\n"); exit(0); } 32 num2.digit = len + 1; 33 if (!(result.num = (char*)malloc(sizeof(char) * (len + 1)))) { printf("内存分配失败\n"); exit(0); } 34 result.digit = 2 * len + 1; 35 for (i = 0; i < result.digit; i++) result.num[i] = 0; 36 printf("选择大整数运算(+,-,*,/): "); 37 fflush(stdin);//刷新标准输入缓冲区,把输入缓冲区里的东西丢弃 38 scanf(" %c", &op); 39 switch (op) { 40 case '+': 41 printf("\n输入被加数:"); scanf("%s", num1.num); 42 printf("\n输入加数:"); scanf("%s", num2.num); 43 bigIntTrans(&num1); 44 bigIntTrans(&num2); 45 bigIntAdd(&num1, &num2, &result); 46 break; 47 case '-': 48 printf("\n输入被减数:"); scanf("%s", num1.num); 49 printf("\n输入减数:"); scanf("%s", num2.num); 50 bigIntTrans(&num1); 51 bigIntTrans(&num2); 52 bigIntSub(&num1, &num2, &result); 53 break; 54 case '*': 55 printf("\n输入被乘数:"); scanf("%s", num1.num); 56 printf("\n输入乘数:"); scanf("%s", num2.num); 57 bigIntTrans(&num1); 58 bigIntTrans(&num2); 59 bigIntMul(&num1, &num2, &result); 60 break; 61 case '/': 62 printf("\n输入被除数:"); scanf("%s", num1.num); 63 printf("\n输入除数:"); scanf("%s", num2.num); 64 bigIntTrans(&num1); 65 bigIntTrans(&num2); 66 if (num2.digit == 1 && num2.num[0] == '0') printf("除数不能为0!\n"); 67 else bigIntDiv(&num1, &num2, &result, &residue); 68 break; 69 } 70 71 if (op == '/') { 72 if (!(num2.digit == 1 && num2.num[0] == '0')) { 73 printf("商:"); bigIntPrint(&result); 74 printf("\t余数:"); bigIntPrint(&residue); 75 } 76 } 77 else {printf("结果:"); bigIntPrint(&result);} 78 79 80 return 0; 81 } 82 83 void bigIntTrans(pBigInt num1) { 84 char* t; 85 int i, k, len; 86 87 len = strlen(num1->num); 88 if (!(t = (char*)malloc(sizeof(char) * len))){printf("内存分配失败!\n");exit(0); } 89 i = 0; 90 num1->minus = 1;//默认为正 91 if (num1->num[0] == '-') { num1->minus = -1; i++; }//若第一个字符试'-',那么则是负数 92 k = 0; 93 while (num1->num[i] != '\0') { 94 if (num1->num[i] >= '0' && num1->num[i] <= '9') { t[k++] = num1->num[i] - '0'; }//将ASCII码转化成对应得数字 95 i++; 96 } 97 98 for (i = 0; i < num1->digit; i++) num1->num[i] = 0;//数组清空 99 num1->digit = k;//转换后得位数 100 for (i = 0, k--; k >= 0; k--, i++) num1->num[i] = t[k];//将临时数组 各位 反置 后存到num中 101 102 bigIntTrim(num1); 103 104 } 105 106 void bigIntTrim(pBigInt num1) { 107 int i; 108 //从高位检查是否为0 109 for (i = num1->digit - 1; i >= 0; i--) { if (num1->num[i] != 0) break; }//遇到不为0得最高位,跳出循环 110 if (i < 0) { num1->digit = 1; num1->num[0] = 0; } 111 else num1->digit = i + 1;//余数位数,因为i对应的是下标,比如对应的i=4,那么下标为0,1,2,3,4的位置上都有数,则为5位数 112 113 } 114 115 void bigIntPrint(pBigInt result) { 116 int i; 117 118 if (result->minus == -1) printf("-"); 119 if (result->digit == 1 && result->num[0] == 0) printf("0\n"); 120 else { 121 for (i = result->digit - 1; i >= 0; i--) 122 printf("%d", result->num[i]); 123 } 124 } 125 126 int bigIntEqual(pBigInt num1, pBigInt num2) { 127 int i; 128 129 if (num1->digit > num2->digit) return 1; 130 else if (num1->digit < num2->digit) return -1; 131 else { 132 i = num1->digit - 1; 133 while (i >= 0) { 134 if (num1->num[i] > num2->num[i]) return 1; 135 else if (num1->num[i] < num2->num[i]) return -1; 136 else i--; 137 } 138 } 139 return 0; 140 } 141 142 void bigIntAdd(pBigInt num1, pBigInt num2, pBigInt result) { 143 int i = bigIntEqual(num1, num2); 144 145 if (i < 0) { pBigInt t; t = num1; num1 = num2; num2 = t; } 146 if (num1->minus * num2->minus < 0) {//符号相同,则加法,不同则减法 147 if (i == 0) {//如果两个数是相等的 148 result->digit = 1;//结果长度为1位数,就是数值0 149 result->minus = 1;//结果为正号 150 result->num[0] = 0;//结果为0 151 return; 152 } 153 bigIntSub1(num1, num2, result);//减法 154 } 155 else bigIntAdd1(num1, num2, result); 156 } 157 158 void bigIntAdd1(pBigInt num1, pBigInt num2, pBigInt result) { 159 int i, carry = 0;//carry代表的 进位 160 161 result->minus = num1->minus; 162 for (i = 0; i < num1->digit; i++) { result->num[i] = num1->num[i]; } 163 for (i = 0; i < num2->digit; i++) { 164 result->num[i] = result->num[i] + num2->num[i] + carry;//将对应的数和进位数相加 165 carry = result->num[i] / 10;//计算进位数据 166 result->num[i] = result->num[i] % 10;//保留一位 167 } 168 169 if (carry) result->num[i] = result->num[i] + carry;//若最后还有进位 170 bigIntTrim(result); 171 } 172 173 void bigIntSub1(pBigInt num1, pBigInt num2, pBigInt result) {//异号相减函数 174 int i, borrow = 0;//borrow低位的借位 175 176 result->minus = num1->minus; 177 for (i = 0; i < num1->digit; i++) result->num[i] = num1->num[i]; 178 for (i = 0; i <= num2->digit; i++) { 179 result->num[i] = result->num[i] - num2->num[i] - borrow; 180 if (result->num[i] < 0) { 181 result->num[i] = 10 + result->num[i]; 182 borrow = 1; 183 } 184 else borrow = 0; 185 } 186 187 if (borrow == 1) result->num[i] = result->num[i] - borrow; 188 i = num1->digit; 189 while (i > 0) { 190 if (result->num[i] == 0) i--; 191 else break; 192 } 193 194 result->digit = i + 1; 195 bigIntTrim(result); 196 } 197 198 void bigIntSub(pBigInt num1, pBigInt num2, pBigInt result) { 199 num2->minus = -1 * num2->minus;//将减数符号取反 200 bigIntAdd(num1, num2, result); 201 } 202 203 void bigIntMul(pBigInt num1, pBigInt num2, pBigInt result) { 204 char carry, t; 205 int i, j, pos; 206 207 for (i = 0; i < num1->digit + num2->digit; i++) result->num[i] = 0;//结果数组清零 208 for (i = 0; i < num2->digit; i++) { 209 carry = 0;//清除进位 210 for (j = 0; j < num1->digit; j++) { 211 t = num2->num[i] * num1->num[j] + carry;//两个数相乘,加上进位 212 carry = t / 10;//进位 213 t %= 10;//计算当前位的值 214 pos = i + j;//看t应该加在哪个位上 215 result->num[pos] += t; 216 carry = carry + result->num[pos] / 10;//主要防止num[pos]大于等于10 217 result->num[pos] = result->num[pos] % 10; 218 } 219 220 if (carry > 0) { 221 result->num[i + j] = carry;//加上最高位的进位 222 result->digit = i + j + 1; 223 } 224 else result->digit = i + j; 225 } 226 227 result->minus = num1->minus * num2->minus; 228 } 229 230 void bigIntDiv(pBigInt num1, pBigInt num2, pBigInt result, pBigInt residue) { 231 bigInt quo1, quo2, residue1; 232 int i, j, k, m;//k保存试商结果,m保存商的位数 233 char t; 234 235 result->minus = num1->minus * num2->minus; 236 residue->num = (char*)malloc(sizeof(char) * (num2->digit + 1));//分配余数空间 237 residue->digit = num2->digit + 1; 238 for (i = 0; i < residue->digit; i++) residue->num[i] = 0;//将余数清零 239 m = 0; 240 for (i = num1->digit - 1; i >= 0; i--) { 241 for (j = residue->digit - 1; j > 0; j--) residue->num[j] = residue->num[j - 1];//移余数 (有问题,等会试一下) 242 residue->num[0] = num1->num[i]; 243 bigIntTrim(residue);//整理余数 244 k = 0; 245 while (bigIntEqual(residue, num2) >= 0) { 246 bigIntSub1(residue, num2, residue); 247 k++; 248 } 249 result->num[m++] = k; 250 251 } 252 253 result->digit = m; 254 for (i = 0; i < m / 2; i++) { 255 t = result->num[i]; 256 result->num[i] = result->num[m - 1 - i]; 257 result->num[m - 1 - i] = t; 258 } 259 260 bigIntTrim(result); 261 bigIntTrim(residue); 262 }