无数次面对这样的问题,两个长度是几千甚至上万的字符串相加或相减,输出结果。这次专门练习写一遍。
校赛ACM时候就卡在这种题上了,不然就能AC七道题了!!
1.两个大数相加的函数比相减的简单些,不用考虑结果会不会是负数的问题。接收到两个字符串和一个要存储和的目标字符串,先反转两个字符串,后以较长字符串为目标,挨个加到存储和的字符串。当当前长度小于短串的时候,每一位再加上短串的对应位,当前位相加后超过9则进位。长度超出短串后,加上长串对应位的同时也要判断当前位有没有超过9。结束后注意判断一下和有没有超出长串的长度(可能会进位),用字符串结束标志'\0'结束目标字符串即可,反转目标字符串后结束函数。
void BigNumAdd(char* a, char* b, char* str) { if (strlen(a)<strlen(b)) { BigNumAdd(b, a, str); return; } reverse(a), reverse(b); for (int i = 0; i <= strlen(a); i++) str[i] = '0'; for (int i = 0; i<strlen(a); i++) { str[i] += a[i] - '0'; if (i<strlen(b)) { int num = str[i] - '0' + b[i] - '0'; if (num>9) { str[i] = num - 10 + '0'; str[i + 1]++; } else { str[i] = num + '0'; } } else { if (str[i]>'9') { str[i] -= 10; str[i + 1]++; } } } if (str[strlen(a)] > '0') str[strlen(a) + 1] = 0; else str[strlen(a)] = 0; reverse(str); }
a和b是相加的两个字符串,str是目标字符串(存储和)
void reverse(char* str) { int ind = strlen(str) - 1; int ins = 0; while (ins<ind) { char ch = str[ind]; str[ind] = str[ins]; str[ins] = ch; ind--, ins++; } return; }
这是用到的反转字符串函数,头尾开始交换,直到中间碰头结束。
2.两个大数相减先考虑的是两数大小问题,只有大数减小数才不会出现负数的情况。我先判断两字符串长度,如果两字符串长度相同再逐位判断大小,长度不满足被减数大于减数则交换被减数和减数,并用返回值来表示此次减法运算是否结果为负。减数和被减数相同则直接赋值目标字符串0,并结束函数。
满足被减数大于减数后,反转两字符串。和大数相加的思路相同,从低位开始逐位判断相减后有没有小于0,如果小于则将高位减一。没有减数后也要逐位判断有没有出现小于0的数。最后要注意的是,高位可能若干位因为被减或借位成0,所以遍历找到第一个不为0的高位。将上一位赋值'\0'结束字符串,反转后完成大数相减。
int BigNumSub(char*a, char* b, char* str) { int i = 0; int j = 0; while (1) { if (strlen(a)<strlen(b)) { BigNumSub(b, a, str); return 1; } if (strlen(a)>strlen(b)) break; else { if (a[i]<b[j]) { BigNumSub(b, a, str); return 1; } if (a[i]>b[j]) break; else { if (i == strlen(a)) { str[0] = '0'; str[1] = 0; return 0; } i++, j++; } } } reverse(a), reverse(b); for (int i = 0; i <= strlen(a); i++) str[i] = '0'; for (int i = 0; i<strlen(a); i++) { str[i] += a[i] - '0'; if (i<strlen(b)) { int num = str[i] - b[i]; if (num<0) { str[i] = num + 10 + '0'; str[i + 1]--; } else { str[i] = num + '0'; } } else { if (str[i]<'0') { str[i] = '9'; str[i + 1]--; } } } int st = strlen(a) - 1; while (str[st] == '0') st--; str[st + 1] = 0; reverse(str); return 0; }
a是被减数字符串,b是减数字符串,str是目标字符串。返回值非0表示结果为负数,为0则为正数或0。
所用到的反转字符串函数同上。
之后再写大数乘法、除法、开方?