1、高精度计算
涉及知识点:数组、流程控制、函数等
要求:用整型数组表示10进制大整数(超过2^32的整数),数组的每个元素存储大整数的一位数字,实现大整数的加减法。
主体思路如下:
由于要求使用数组储存,首先使用字符的方式读取输入,通过数组的第一位储存正负符号。
当输入的数据存在负数时,我们的想法便是将其转换为两个正数的加减。这样事实上只需要考虑正整数的加法和正整数的减法即可,具体代码如下:
#include
#include
#include
#define max(a,b) (a)>(b)?(a):(b)
const int MAX = 100;//最大存储位数
int mark = 1; //判定字符串转换为数组是是否产生错误
int length = 0;//记录答案的长度
int* add(int* num1 , int* num2,int len1, int len2);
int* decre(int* num1 , int* num2 , int len1 , int len2);
void swap(int* a, int* b);
void change(int *num , char* s);
int main(){
char s1[100];
char s2[100];
int num1[100];
int num2[100];
char ch = '-';
int len1 = 0, len2 = 0;
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
printf("Please input num1:\n");
scanf("%s",&s1);getchar();
change(num1,s1);
len1 = strlen(s1);
if(s1[0] == '-')
len1--;
if(mark == 0){
printf("Sorry ! Erroe input!");
return 0;
}
printf("Please intput operator(+ or -): \n");
scanf("%c",&ch);getchar();
if(ch != '+' && ch != '-'){
printf("Sorry ! Erroe input!");
return 0;
}
printf("Please input num2:\n");
scanf("%s",&s2);getchar();
change(num2,s2);
len2 = strlen(s2);
if(s2[0] == '-')
len2--;
if(mark == 0){
printf("Sorry ! Erroe input!");
return 0;
}
puts(s1);
printf("%c\n",ch);
puts(s2);
puts("Answer:");
if(ch == '+'){
int *ans = add(num1,num2,len1,len2);
for(int i = 0; i < length; i ++){
printf("%d",ans[i]);
}
}else{
int *ans = decre(num1,num2,len1,len2);
for(int i = 0; i < length; i ++){
printf("%d",ans[i]);
}
}
return 0;
}
void swap(int* a, int* b){
int t = *a;
*a = *b;
*b = t;
}
//比较两个正整数的大小
int cmp(int* num1, int* num2, int len1 , int len2){
if(len1 > len2){
return 1; //num1 > num2
}else if(len2 > len1){
return -1; // num2 > num1
}else{
for(int i = 0; i < len1; i ++){
if(num1[i] > num2[i])
return 1;
else if(num2[i] > num1[i])
return -1;
}
}
return 0;//相等
}
int* add(int* num1 , int* num2,int len1, int len2){
//符号相反
if(num1[0]*num2[0]<0){
//找出其中的负数并返回减法的结果
if(num1[0]<0){
num1[0] = -num1[0];
return decre(num2,num1,len2,len1);
}else{
num2[0] = -num2[0];
return decre(num1,num2,len1,len2);
}
}
//负数相加时先将首位符号变为正,并使用flag标记
int flag = 0;
if(num1[0] < 0){
flag = 1;
num1[0] = -num1[0];
num2[0] = -num2[0];
}
int maxlen = max(len1 , len2);
int* ans = (int*)malloc(sizeof(int)*(maxlen+1));
for(int i = 0; i <= maxlen ; i ++){
ans[i] = 0;
}
int i = len1-1;
int j = len2-1;
int k = 0;
int las = 0;
//模拟十进制加法并将结果倒序保存
while(i >= 0 || j >= 0 || las != 0){
if(i >= 0)
las += num1[i--];
if(j >= 0)
las += num2[j--];
ans[k++] = las%10;
las /= 10;
}
i = 0;
j = k-1;
length = k;
//反转数组
while(i < j){
swap(&ans[i++],&ans[j--]);
}
if(flag == 1)
ans[0] = -ans[0];
return ans;
}
//num1 - num2
int* decre(int* num1 , int* num2 , int len1 , int len2){
if(num1[0]*num2[0] < 0){
//符号相反
num2[0] = -num2[0];
return add(num1,num2,len1,len2);
}else if(num1[0] == 0){//存在0
num2[0] = -num2[0];
length = len2;
return num2;
}else if(num2[0] == 0){//存在0
length = len1;
return num1;
}
//符号相同的情况
if(num2[0]<0){ //负数 - 负数 -> 正数 - 正数
num2[0] = -num2[0];
return decre(num2,num1,len2,len1);
}
//到这里就只需考虑 正数 - 正数了
if(cmp(num1,num2,len1,len2) < 0){ //小 - 大则改为 大-小
int* res = decre(num2,num1,len2,len1);
//将结果的符号修改为负
res[0] = -res[0];
return res;
}else if( cmp(num1,num2,len1,len2)==0){//相同就立刻返回
return {0};
}
int maxlen = max(len1 , len2);
int* res = (int*)malloc(sizeof(maxlen));
for(int i = 0; i < maxlen; i ++){
res[i] = 0;
}
int i = len1-1;
int j = len2-1;
int k = 0;
int las = 0;
//模拟减法倒序记录
while(j >= 0 || i >= 0 || las != 0){
int tmp = num1[i--] + las;
if(j >= 0)
tmp -= num2[j--];
las = tmp<0 ? -1:0;
res[k++] = tmp>=0 ? tmp : tmp+10;
}
i = 0;
j = k-1;
//反转数组
while(i<j){
swap(&res[i++] , &res[j--]);
}
//除去前端多余的0操作
int index = 0;
while(res[index] == 0){
index ++;
}
int t = index;
for(int i = 0; index < k; i ++, index++){
res[i] = res[index];
}
k -= t;
length = k;
return res;
}
void change(int *num , char* s){
int len = strlen(s);
int i = 0;
int t = 0;
if(s[0] == '-'){
num[t++] = -(s[1] - '0');
i = 2;
}
while(i < len){
if(s[i]<'0' || s[i]>'9'){
mark = 0;
return ;
}
num[t++] = (s[i++]-'0');
}
}