Boj上的A-B题目:
首先,看到这个题,应该觉察到是一个大数运算的问题,如果是实际开发,对性能没什么要求,无需自己写,因为java等语言里已经能够支持大数运算。
其次,据说十年前的大牛的补码解决方案就已经完美解决了这个问题。但我还是只能按照普通的逻辑来做,需要注意的有以下几点:
1.用无符号字符数组存储大数。
2.对输入判断做加法还是做减法。
3. 加法,对应位置字符直接减字符0转换为整数后相加,全部相加后,循环将大于10的-10,其前面的数加一(即进位),最后一个数不用检查,直接输出即可。
4. 减法,一种是借一位(即上一位——大于零——够借,则直接本位字符加上char(10),上一位减去char(1)。若不够借——等于零——则加上char(9)继续向上借,直到借到,将哪一位减去 char(1)。
测试用例:
-1 , 100;
1 , 1100;
0 ,0;
-999,-999
9999999999999,-999999999999999999999999
个人代码留作以后修改。
#include <stdio.h>
int compare(char * , char *);
void print(int *, int);
void rectify(char *);
int* minus(char * , char * );
int * add(char * , char *);
int main()
{
unsigned char a[105];
unsigned char b[105];
int *result;
char calSign = '-';
char resSign = '+';
scanf("%s%s",a ,b);
//a 为负,b为正
if( a[0] == '-' && b[0] != '-' )
{
int i = 0;
for( i = 0; i < strlen(a);i++ )
{
a[i] = a[i+1];
}
calSign = '+';
resSign = '-';
}
//a为正b为负
if( a[0] != '-' && b[0] == '-')
{
int i = 0;
for( i = 0; i < strlen(b); i++ )
{
b[i] = b[i+1];
}
calSign = '+';
resSign = '+';
}
//a为负b为负
if( a[0] == '-' && b[0] == '-')
{
int i = 0;
for( i = 0; i < strlen(a); i++ )
{
a[i] = a[i+1];
}
for( i = 0; i < strlen(b);i++ )
b[i] = b[i+1];
calSign = '-';
resSign = '-';
}
rectify(a);
rectify(b);
if( calSign == '+' )
{
//int res = 0;
if( strlen(a) > strlen(b) )
{
result = add(a ,b );
if( resSign == '-' )
printf("%c", resSign);
int n;
for(n = 0;n< strlen(a);n++)
{
printf("%d",result[n]);
}
}
else
{
result = add(b , a);
if( resSign == '-' )
printf("%c", resSign);
int n ;
for(n=0 ;n< strlen(b);n++)
{
printf("%d",result[n]);
}
}
// printf("\n");
}
else if( calSign == '-')
{
int com = compare(a ,b);
if( com > 0 )
{
result = minus(a , b);
int i = 0;
if( resSign == '-' )
printf("%c" , resSign);
print(result, strlen(a));
}
else if( com == 0 )
{
printf("%d", 0 );
}
else if( com < 0 )
{
result = minus(b,a);
int i = 0;
if( resSign == '-' )
resSign = '+';
else
resSign = '-';
if( resSign == '-')
printf("%c",resSign);
print(result, strlen(b));
}
}
printf("\n");
// printf("%d\n", a);
// printf("%s\t%s\n",a,b);
// printf("%d\n",strlen(a));
// printf("%d\n",sizeof(a));
return 0;
}
void rectify(char * rec)
{
int sign = 0;
int i;
for(i = 0; i < strlen(rec);i++)
{
if( rec[i] == '0' )
sign++;
else
break;
}
//printf("%d",sign);
if( sign != 0 )
{
if( sign == strlen(rec) )
{
rec[1]='\0';
}
else
{
for( i = 0;(i+sign) <= strlen(rec);i++ )
{
rec[i] = rec[i + sign];
}
// rec[strlen(rec)-sign]= '\0';
}
}
}
void print(int * result ,int n)
{
int yes = 0;
int i;
for(i = 0 ; i < n; i++ )
{
if( yes == 0 )
{
if( result[i] == 0 )
continue;
else
{
yes = 1;
printf("%d", result[i]);
}
}
else
printf("%d",result[i]);
}
}
int compare(char * x, char * y)
{
if( strlen(x) != strlen(y))
return strlen(x) > strlen(y)?1:-1;
return strcmp( x , y );
}
int * minus(char * big, char *small)
{
int * result = malloc(sizeof(int)* (strlen(big)+1)) ;
int i = strlen(big)-1;
int j = strlen(small)-1;
for( ;i >=0;i-- )
{
if( big[i] >= small[j])
{
// printf("%c",big[i]);
result[i] = big[i]-small[j];
}
else
{
big[i] = big[i]+ (char)10;
int k = i-1;
for(; k >=0;k--)
{
if( big[k] < '1' )
{
big[k] += (char)9;
}
else
{
big[k] -=(char)1;
break;
}
}
result[i] = big[i]-small[j];
}
j--;
if( j < 0 && i > 0 )
{
int k = i-1;
for( ;k >=0; k-- )
{
result[k]= (int)(big[k] - '0');
}
break;
}
}
return result;
}
int* add(char* a, char *b )
{
int i = strlen(a) - 1;
int j = strlen(b) - 1;
int * result = malloc(sizeof(int) * (strlen(a)+ 1));
for( ; i >= 0; i-- )
{
result[i] = (int)( (int)(a[i]- '0') + (int)( b[j] - '0' ));
// printf("%d",result[i]);
j--;
if( j < 0 && i > 0 )
{
int k = i-1;
for( ;k>= 0; k-- )
result[k]= (int)(a[k] - '0');
break;
}
}
int x = strlen(a) - 1;
int temp = 1;
int res = 0;
for( ;x >0; x-- )
{
if( result[x] >= 10 )
{
result[x] -= 10;
result[x-1] += 1;
}
}
return result;
}