大数加减乘以及高精度幂
我们都知道int, long, long long 等数据类型,但是如果一个数字过长的话,这些数据所定义的变量就放不下了,这时就要用到大数,所谓大数,就是比较大的数,超出了我们平时long long所定义的范围,这时可以用数组将它存放起来,用模拟手算的方式来让计算机计算,下面试关于大数的加减乘及高精度幂的代码实现
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #define NUM 10001//定义数组长度 5 void showmeau(); 6 void change(char *ch1, char *ch2); 7 void add(char *ch1, char *ch2); 8 void sub(char *ch1, char *ch2); 9 void Input(); 10 void add_big_number(); 11 void sub_big_number(); 12 void multi(char *ch1, char *ch2); 13 void multi_big_number(); 14 void exchange(char *ch, int *count); 15 void multi_power(char *ch, int n, int count); 16 void high_precision_power(); 17 18 char s1[NUM], s2[NUM]; int n, flag = 0; 19 int main() 20 { 21 showmeau(); 22 return 0; 23 } 24 void showmeau() 25 { 26 do{ 27 system("cls");//调用系统命令清屏 28 printf("1. big number add 2. big number sub \n3.big number multi 4. High precision power \n\t\t0. exit\n"); 29 scanf("%d", &n); 30 switch(n) 31 { 32 case 1: 33 add_big_number(); 34 break; 35 case 2: 36 sub_big_number(); 37 break; 38 case 3: 39 multi_big_number(); 40 break; 41 case 4: 42 high_precision_power(); 43 break; 44 case 0: 45 break; 46 default: 47 printf("your input error!\n"); 48 break; 49 } 50 system("pause"); 51 }while(n != 0); 52 53 } 54 55 void Input() 56 { 57 printf("Input the first big number:\n"); 58 scanf("%s", s1); 59 printf("Input the second big number:\n"); 60 scanf("%s", s2); 61 } 62 void change(char *ch1, char *ch2)//去掉负号函数 63 { 64 int len1 = strlen(ch1), len2 = strlen(ch2); 65 int i; 66 char str1[NUM], str2[NUM]; 67 switch(flag) 68 { 69 case 1: 70 for(i = 0; i < len1 - 1; i ++)//如果都是负数的时候执行到ch1[1]; 71 str1[i] = ch1[len1 - i - 1]; 72 str1[i] = '\0'; 73 for(i = 0; i < len2 - 1; i ++) 74 str2[i] = ch2[len2 - i - 1]; 75 str2[i] = '\0'; 76 break; 77 case 2: 78 for(i = 0; i < len1 - 1; i ++)//如果一正一负的话 79 str1[i] = ch1[len1 - i - 1]; 80 str1[i] = '\0'; 81 for(i = 0; i < len2; i ++) 82 str2[i] = ch2[len2 - i - 1]; 83 str2[i] = '\0'; 84 break; 85 case 3: 86 for(i = 0; i < len1; i ++)//如果一正一负的话 87 str1[i] = ch1[len1 - i - 1]; 88 str1[i] = '\0'; 89 for(i = 0; i < len2 - 1; i ++) 90 str2[i] = ch2[len2 - i - 1]; 91 str2[i] = '\0'; 92 break; 93 case 4://如果都是正的 94 for(i = 0; i < len1; i ++) 95 str1[i] = ch1[len1 - i - 1]; 96 str1[i] = '\0'; 97 for(i = 0; i < len2; i ++){ 98 str2[i] = ch2[len2 - i - 1]; 99 } 100 str2[i] = '\0'; 101 break; 102 default: 103 break; 104 } 105 memset(ch1, 0, sizeof(ch1));//将ch1清空 106 memset(ch2, 0, sizeof(ch2));//将ch2清空 107 strcpy(ch1, str1); 108 strcpy(ch2, str2); 109 } 110 void add(char *ch1, char *ch2)//执行加法过程 111 { 112 int len1 = strlen(ch1), len2 = strlen(ch2); 113 int t = 0, j;//t为进位; 114 int num[NUM] = {0}, i; 115 int max = len1 > len2 ? len1 : len2;//找出最大的长度来进行确定循环次数 116 for(i = 0; i < max; i ++) 117 { 118 if(len1 <= i) 119 { 120 if(ch2[i] + t - '0' > 9)//这是一位一位的进, 121 { 122 num[i] = ch2[i] - '0' + t - 10;//只保存最后一位 123 t = 1; 124 } 125 else 126 { 127 num[i] = ch2[i] - '0' + t; 128 t = 0; 129 } 130 continue; 131 } 132 else if(len2 <= i) 133 { 134 if(ch1[i] + t - '0' > 9) 135 { 136 num[i] = ch1[i] - '0' + t - 10; 137 t = 1; 138 } 139 else 140 { 141 num[i] = ch1[i] - '0' + t; 142 t = 0; 143 } 144 continue; 145 } 146 if(ch1[i] - '0' + ch2[i] - '0' + t > 9) 147 { 148 num[i] = ch1[i] + ch2[i] + t - '0' - '0' - 10; 149 t = 1; 150 } 151 else 152 { 153 num[i] = ch1[i] + ch2[i] + t - '0' - '0'; 154 t = 0; 155 } 156 } 157 if(t == 1) 158 num[i] = 1; 159 if(num[i] == 1) 160 j = i; 161 else 162 j = i - 1; 163 for(; j >= 0; j --) 164 printf("%d", num[j]); 165 printf("\n"); 166 } 167 void sub(char *ch1, char *ch2)//减法过程函数 168 { 169 char ch[NUM]; int num[NUM] = {0}; 170 memset(ch, 0, sizeof(ch)); 171 int flag = 0, i, j; char str1[NUM], str2[NUM]; 172 int len1 = strlen(ch1), len2 = strlen(ch2); 173 if(len1 < len2)//判断两个数的大小,大的在前 174 { 175 strcpy(ch, ch1); 176 strcpy(ch1, ch2); 177 strcpy(ch2, ch); 178 flag = 1;//如果交换了,则说明前面的小,所以最后一定是负数 179 } 180 else if(len1 == len2)//当他们等长时,在比较究竟谁大一点 181 { 182 for(i = 0; i < len1; i ++) 183 str1[i] = ch1[len1 - i - 1]; 184 str1[i] = '\0'; 185 for(i = 0; i < len2; i ++) 186 str2[i] = ch2[len2 - i - 1]; 187 str2[i] = '\0'; 188 if(strcmp(str1, str2) < 0) 189 { 190 strcpy(ch, ch1); 191 strcpy(ch1, ch2); 192 strcpy(ch2, ch); 193 flag = 1; 194 } 195 } 196 len1 = strlen(ch1); len2 = strlen(ch2); 197 int t = 0;//定义借位 198 for(i = 0; i < len1; i ++) 199 { 200 if(len2 <= i) 201 { 202 if(ch1[i] - '0' + t < 0) 203 { 204 num[i] = 10 + ch1[i] - '0' + t; 205 t = -1; 206 } 207 else 208 { 209 num[i] = ch1[i] - '0' + t; 210 t = 0; 211 } 212 continue; 213 } 214 if(ch1[i] + t < ch2[i]) 215 { 216 num[i] = 10 + ch1[i] - ch2[i] + t; 217 t = -1; 218 } 219 else 220 { 221 num[i] = ch1[i] - ch2[i] + t; 222 t = 0; 223 } 224 } 225 if(flag) 226 printf("-");//如果交换了,说明第一个数小于第二个数,要打印负号 227 for(i = len1; i >= 0; i --)//这里判断第一个数不为零的下标 228 if(num[i] != 0) 229 break; 230 if(i == -1) 231 printf("0"); 232 for(j = i; j >= 0; j --)//从这个不为零的下标开始打印 233 printf("%d", num[j]); 234 printf("\n"); 235 } 236 void multi(char *ch1, char *ch2)//乘法函数 237 { 238 int len1 = strlen(ch1), len2 = strlen(ch2); 239 int num[NUM] = {0}, i, j; 240 for(i = 0; i < len1; i ++) 241 { 242 for(j = 0; j < len2; j ++) 243 { 244 num[i + j] += (ch1[i] - '0') * (ch2[j] - '0');//先将各个数的乘积保存到int型变量数组中,即num中,然后最后在进行进位 245 } 246 } 247 int t = 0, tmp;//临时变量来保存num + t 的值,因为一计算num[i],num就变啦 248 for(i = 0; i < len1 + len2 - 1; i ++) 249 { 250 if(num[i] + t > 9) 251 { 252 tmp = num[i] + t; 253 num[i] = (t + num[i]) % 10; 254 t = tmp / 10;//t用来保存进位 255 256 } 257 else 258 { 259 num[i] += t; 260 t = 0; 261 } 262 } 263 while(t > 9)//如果最后一位不为零,说明有进位 264 { 265 num[i ++] = t % 10; 266 t = t / 10; 267 } 268 if(t != 0) 269 num[i] = t; 270 if(num[i] != 0) 271 j = i; 272 else 273 j = i - 1; 274 for(; j >= 0; j --) 275 printf("%d", num[j]); 276 printf("\n"); 277 278 } 279 void exchange(char *ch, int *count)//逆置函数 280 { 281 int len = strlen(ch), i, j; 282 char str[NUM]; 283 j = 0; 284 for(i = len -1; i >= 0; i --)//判断如果后面有多余的零, 清除掉 285 { 286 if(ch[i] == '0') 287 { 288 len --; 289 } 290 else 291 break; 292 } 293 for(; i >= 0; i --) 294 { 295 if(ch[i] == '.')//当读到点的时候,这时记录小数点位数,将它存入count中 296 { 297 *count = len - i - 1; 298 continue; 299 } 300 str[j++] = ch[i]; 301 } 302 str[j] = '\0';//字符串结束符 303 strcpy(ch, str); 304 } 305 void multi_power(char *ch, int n, int count) 306 { 307 int i, j, k, y; char ch1[NUM], ch2[NUM];//ch1用来存放计算时的第一个数,ch2用来存放临时结果 308 memset(ch1, 0, sizeof(ch1)); 309 memset(ch2, 0, sizeof(ch2)); 310 strcpy(ch1, ch); int t = 0; 311 for(i = 1; i < n; i ++)//一共循环n-1次 312 { 313 314 for(j = 0; j < strlen(ch); j ++)//执行大数加法运算,这时的数已经没有小数点了 315 { 316 t = 0; int tmp = 0; 317 for(k = 0; k < strlen(ch1); k ++) 318 { 319 ch2[j + k] += (ch[j] - '0') * (ch1[k] - '0');//将它存入ch2中 320 if(ch2[j + k] + t > 9)//判断是否满足进位,此时存入的是ascii码 321 { 322 tmp = ch2[j + k] + t; 323 ch2[j + k] = (ch2[j + k] + t) % 10; 324 t = tmp / 10; 325 } 326 else 327 { 328 ch2[j + k] += t; 329 t = 0; 330 } 331 } 332 y = j + k; 333 while(t > 9)//判断到最后还有没有进位 334 { 335 ch2[y ++] = t % 10; 336 t /= 10; 337 } 338 if(t != 0)//最后一个进位 339 ch2[y++] = t; 340 } 341 ch2[y] = '\0';//结束符 342 memset(ch1, 0, sizeof(ch1));//将ch1清空 343 int x; 344 for(x = 0; x < y; x ++) 345 { 346 ch2[x] += '0';//将ascii转化成字符123... 347 } 348 strcpy(ch1, ch2); 349 memset(ch2, 0, sizeof(ch2)); 350 } 351 int flag = 0; 352 for(i = strlen(ch1) - 1; i >= 0; i --)//打印出来结果 353 { 354 if(i == n * count - 1) 355 { 356 printf("."); 357 flag = 1; 358 } 359 if(flag) 360 { 361 if(ch1[i] == 0) 362 continue; 363 } 364 printf("%c", ch1[i]); 365 } 366 printf("\n"); 367 } 368 void add_big_number() 369 { 370 Input(); 371 if(s1[0] == '-' && s2[0] == '-')//如果两个数都为负数 372 flag = 1; 373 else if(s1[0] == '-' && s2[0] != '-')//如果一正一负 374 flag = 2; 375 else if(s1[0] != '-' && s2[0] == '-')//如果一正一负 376 flag = 3; 377 else//如果全为正 378 flag = 4; 379 change(s1, s2);//调用交换函数,将它们调整好顺序,去掉负号,并且将字符串逆序 380 switch(flag) 381 { 382 case 1: 383 printf("-"); 384 add(s1, s2);//调用加法函数输出结果 385 break; 386 case 2: 387 sub(s2, s1);//调用减法函数来计算结果并将其输出 388 break; 389 case 3: 390 sub(s1, s2);//调用减法函数来计算结果并将其输出 391 break; 392 case 4: 393 add(s1, s2);//调用加法函数输出结果 394 break; 395 } 396 } 397 398 void sub_big_number() 399 { 400 Input(); 401 if(s1[0] == '-' && s2[0] == '-')//如果两个数都为负数 402 flag = 1; 403 else if(s1[0] == '-' && s2[0] != '-')//如果一正一负 404 flag = 2; 405 else if(s1[0] != '-' && s2[0] == '-')//如果一正一负 406 flag = 3; 407 else//如果全为正 408 flag = 4; 409 change(s1, s2);//调用交换函数,将它们调整好顺序,去掉负号,并且将字符串逆序 410 switch(flag) 411 { 412 case 1: 413 sub(s2, s1);//调用减法函数输出结果 414 break; 415 case 2: 416 printf("-"); 417 add(s1, s2);//调用加法函数来计算结果并将其输出 418 break; 419 case 3: 420 add(s1, s2);//调用加法函数来计算结果并将其输出 421 break; 422 case 4: 423 sub(s1, s2);//调用减法函数输出结果 424 break; 425 } 426 } 427 void multi_big_number() 428 { 429 Input(); 430 if(s1[0] == '-' && s2[0] == '-')//如果两个数都为负数 431 flag = 1; 432 else if(s1[0] == '-' && s2[0] != '-')//如果一正一负 433 flag = 2; 434 else if(s1[0] != '-' && s2[0] == '-')//如果一正一负 435 flag = 3; 436 else//如果全为正 437 flag = 4; 438 change(s1, s2); 439 if(flag == 2 || flag == 3) 440 printf("-"); 441 multi(s1, s2); 442 } 443 void high_precision_power() 444 { 445 int n, count = 0; 446 printf("Input the high precision power number:\n"); 447 scanf("%s", s1); 448 printf("Input the power number:\n"); 449 scanf("%d", &n); 450 exchange(s1, &count); 451 multi_power(s1, n, count); 452 }