1011 A+B和C (15)(15 分)提问
给定区间[-2^31^, 2^31^]内的3个整数A、B和C,请判断A+B是否大于C。
输入格式:
输入第1行给出正整数T(<=10),是测试用例的个数。随后给出T组测试用例,每组占一行,顺序给出A、B和C。整数间以空格分隔。
输出格式:
对每组测试用例,在一行中输出“Case #X: true”如果A+B>C,否则输出“Case #X: false”,其中X是测试用例的编号(从1开始)。
输入样例:
4
1 2 3
2 3 4
2147483647 0 2147483646
0 -2147483648 -2147483647
输出样例:
Case #1: false
Case #2: true
Case #3: true
Case #4: false
问题分析: 这道题卡了我挺长时间的,主要是对计算机存储数据的方式不熟,一开始觉着用int型,不考虑大数,感觉大数有点麻烦就偷了个懒,后来发现测试案例部分正确,后来就改了,int 4个字节 只能存储-2^31-2^31-1 范围内的数,所以该题不能用int。可以用long long 或者double 8个字节,-2^63-2^63-1,都能解决这个问题。但我后面是利用大数搞定的,花了一下午的时间,完成大数的加减乘,除法涉及到小数,需要用到浮点运算,比较麻烦,我就没写了。
小知识:int 4个字节 -2^31-2^31-1,数据大小长度小于10位 ;long long或者double 8个字节 数据大小长度小于19位;如果题目给的数据大于19位长度,则应使用字符串大数。如果用到long long,必需注意格式输入与输出,这个地方的错误我找了一个半小时,long long 8字节 64位,可以使用%I64d(g++)或者%lld(gcc)格式输入或输出,具体区别可参考这篇博文https://blog.csdn.net/piaocoder/article/details/50254117。下一章介绍大数。
算法分析:确定了数据大小,那这道题很容易就可以写出来,最近喜欢用链表,喜欢模块化编程,所以每次程序都有些长。下面分别给出long long 以及字符串大数两种代码。
long long:
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode *List;
struct LNode{
long long A;
long long B;
long long C;
List next;
};
List ReadInput(int n);
void fun(List L); /* 判断A+B>C */
int main()
{
long long n=1;
int m=1,i;
printf("%d",sizeof(long long));
for(i=0;i<30;i++) /* 2^0+...+2^x=2^31-1 */
m=(m<<1)+1; /* << 优先级小于+ */
for(i=0;i<62;i++)
n=(n<<1)+1;
printf("m=%d,n=%I64d",m,n);
/* List L,P;
int n;
scanf("%d",&n);
L = ReadInput(n);
/* for(P=L;P!=NULL;P=P->next)
printf("%I64d %I64d %I64d",P->A,P->B,P->C);
*/
// fun(L);
return 0;
}
List ReadInput(int n)
{
List L,P,t;
int i=0;
L = (List)malloc(sizeof(struct LNode));
P = L;
for(; i<n; i++)
{
t = P;
scanf("%lld%lld%lld",&P->A,&P->B,&P->C);
/* 注意:long long 8字节 64位,可以使用%I64d(g++)或者%lld(gcc)格式输入或输出 */
P = (List)malloc(sizeof(struct LNode));
t->next = P;
}
free(P);
t->next = NULL;
return L;
}
void fun(List L) /* 判断A+B>C */
{
List P=L;
int i=1;
for(; P->next!=NULL; P=P->next,i++)
{
if(P->A + P->B > P->C)
printf("Case #%d: true\n",i);
else printf("Case #%d: false\n",i);
}
if(P->A + P->B > P->C)
printf("Case #%d: true",i);
else
printf("Case #%d: false",i);
}
字符串数组大数(自己写的,代码有点长,有更简洁实现的欢迎交流进步):
#include <stdio.h>
#include <stdlib.h>
#define Length 13+1
typedef struct LNode *List;
struct LNode{
char A[Length];
char B[Length];
char C[Length];
List next;
};
List ReadInput(int n);
void fun(List L); /* 判断A+B>C */
void LInput(char *a); /* 大数输入 */
void LOutput(char *a); /* 大数输出 */
int StrLen(char *a); /* 求大数长度 */
int Compare(char *a,char *b); /* a,b为整数,a>b 返回1,否则返回0 */
int PCompare(char *a,char *b); /* a,b均大于0,a>b 返回1,否则返回0 */
void fun1(char *a,char *b,char *t); /* 大数为正相加 */
void fun2(char *a,char *b,char *t); /* 大数为正相减 */
void LAdd(char *a,char *b,char *c); /* 大数相加 */
int main()
{
List L,P;
int n;
scanf("%d",&n);
L = ReadInput(n);
fun(L);
return 0;
}
List ReadInput(int n)
{
List L,P,t;
int i=0;
L = (List)malloc(sizeof(struct LNode));
P = L;
getchar();
for(; i<n; i++)
{
t = P;
LInput(P->A);
LInput(P->B);
LInput(P->C);
P = (List)malloc(sizeof(struct LNode));
t->next = P;
}
free(P);
t->next = NULL;
return L;
}
void fun(List L) /* 判断A+B>C */
{
List P=L;
char t[Length];
int i=1;
for(; P->next!=NULL; P=P->next,i++)
{
LAdd(P->A,P->B,t);
// LOutput(t);
if(Compare( t, P->C))
printf("Case #%d: true\n",i);
else printf("Case #%d: false\n",i);
}
LAdd(P->A,P->B,t);
// LOutput(t);
if(Compare( t, P->C))
printf("Case #%d: true",i);
else printf("Case #%d: false",i);
}
void LInput(char *a) /* 大数输入,最高位前面的初始化为'0' */
{
int i,j;
char t;
for(i=0;i<Length;i++)
{
scanf("%c",&a[i]);
if(a[i]=='\n' || a[i]==' ')
{
j=i-1; /* 记住输入字符长度 */
while(i<Length) a[i++]='0'; /* 补零 */
break;
}
}
if(i==Length) a[i-1]='\0'; /* 字符串最后一位'\0' */
/* 逆序,高位存储在高字节 */
for(i=0;i<=j;i++,j--)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
void LOutput(char *a) /* 大数输出 */
{
int j=StrLen(a)-1;
if(a[0]=='\0') printf("溢出\n");
if(j==-1) printf("%d",a[j]); /* 0 的情况 */
else
for(;j>=0;j--)
printf("%c",a[j]);
printf("\n");
}
int StrLen(char *a) /* 求大数长度,包括正负号 */
{
int i;
while(*a) a++; /* 从后序开始查找 */
for(i=0;;i++)
if(*--a !='0') break;
return Length-i-1;
}
int Compare(char *a,char *b) /* a>b 返回1,否则返回0 */
{
int L1=StrLen(a)-1,L2=StrLen(b)-1;
char a1[Length],a2[Length],i;
/* a>=0,b<0 */
if(a[L1]!='-' && b[L2]=='-')
return 1;
/* a<0,b>=0 */
if(a[L1]=='-' && b[L2]!='-') return 0;
/* a<0,b<0 */
for(i=0;i<Length;i++) /* 先存储,再使用,防止a,b的值被改变 */
{
a1[i] = a[i];
a2[i] = b[i];
}
if((a[L1] == '-') && (b[L2] == '-'))
{
a1[L1]=a2[L2]='0';
if(PCompare(a1,a2)) return 0;
else return 1;
}
/* a>=0,b>=0 */
return PCompare(a1,a2);
}
int PCompare(char *a,char *b) /* a,b均大于0,a>b 返回1,否则返回0 */
{
int l1=StrLen(a)-1,l2=StrLen(b)-1;
if(l1>l2)
return 1;
if(l1<l2)
return 0;
for(;l1>=0;l1--)
{
// printf("a[%d]=%c,b[%d]=%c\n",l1,a[l1],l1,b[l1]);
if(a[l1]>b[l1]) return 1;
if(a[l1]<b[l1]) return 0;
}
return 0;
}
void LAdd(char *a,char *b,char *c) /* 大数相加 */
{
int L1=StrLen(a)-1,L2=StrLen(b)-1,l;
/* a>0,b>0,a+b */
if(a[L1]!='-' && b[L2]!='-')
fun1(a,b,c);
/* a>0,b<0,转化成a-|b| */
if(a[L1]!='-' && b[L2]=='-')
{
b[L2]='0';
if(Compare(a,b)) /* 若a>=|b|,则a-|b|,否则-(|b|-a) */
fun2(a,b,c);
else
{
fun2(b,a,c);
c[StrLen(c)]='-';
}
}
/* a<0,b>0,转化成b-|a| */
if(a[L1]=='-' && b[L2]!='-')
{
a[L1]='0';
if(Compare(b,a)) /* 若b>=|a|,则b-|a|,否则-(|a|-b) */
fun2(b,a,c);
else
{
fun2(a,b,c);
c[StrLen(c)]='-';
}
}
/* a<0,b<0,转化成-(|b|+|a|) */
if(a[L1]=='-' && b[L2]=='-')
{
a[L1]='0';
b[L2]='0';
fun1(a,b,c);
l=StrLen(c);
c[l]='-';
}
}
void fun1(char *a,char *b,char *t) /* 大数为正相加 */
{
int i,c=0,s; /* c进位 */
for(i=0;i<Length;i++)
{
s = a[i]-'0'+b[i]-'0';
if(s<10)
{
t[i]=s+'0'+c;
c=0;
}
else
{
t[i]=s-10+'0'+c;
c=1;
}
}
if(c == 1) /* 最高位进位,溢出 */
t[0] = '\0';
else
t[i-1] = '\0';
}
void fun2(char *a,char *b,char *t) /* 大数为正相减,且a>b */
{
int i,c=0,s; /* c借位 */
for(i=0;i<Length;i++)
{
s = a[i]-'0'-(b[i]-'0');
if(s>=0)
{
t[i]=s+'0'-c;
c=0;
}
else
{
t[i]=s+10+'0'-c;
c=1;
}
}
if(c == 1) /* 最高位借位,溢出 */
t[0] = '\0';
else
t[i-1] = '\0';
}