主要问题是运算过程中的溢出,为防止溢出必须用简约式的运算过程,比如若case是
5
1/2 16/32 1073741824/32768 1073741824/1073741824 1073741824/2147483646
最安全的做法是先对输入的分数约分,计算过程中的每一步进行约分,保证运算过程中分子的加法运算过程尽量不溢出,通分时分母乘法运算过程尽量不溢出。
分子的加法运算时溢出如
1/2+16/32=32/32
32/32+1073741824/32768=1073774592/32768
1073774592/32768+1073741824/1073741824=((2^15+1)*2^30+2^30/2^30)这里就乘法溢出了
分母的乘法运算中的溢出如
1073741824/1073741824+1073741824/2147483646
1073741824=2^30
2147483646/2=1073741823是个奇数,它必有一个因数x>2.
2^30*x>2^31这里发生了乘法溢出
故按照保守的想法,程序如下
#include<stdio.h> #include<math.h> typedef struct fraction { long long it;//integer long long nmr;//numerator long long dnm;//denominator }fraction; int main() { long long EUCLID_GCD (long long a,long long b);//GCD=greatest_common_divisor long long n,i,gcd=1,it=0,nm=0,sum=0,cd=1,cd0=1;//cd=common_denominator scanf("%lld",&n); getchar(); fraction frc[n]; for(i=0;i<n;i++) { scanf("%lld/%lld",&frc[i].nmr,&frc[i].dnm); gcd=EUCLID_GCD(abs(frc[i].nmr),abs(frc[i].dnm)); frc[i].nmr=frc[i].nmr/gcd; frc[i].dnm=frc[i].dnm/gcd; frc[i].it=frc[i].nmr/frc[i].dnm; frc[i].nmr=frc[i].nmr%frc[i].dnm; getchar(); //simplification } for(i=0;i<n;i++) { cd0=cd; gcd=EUCLID_GCD(abs(cd),abs(frc[i].dnm)); cd=(frc[i].dnm/gcd)*cd; //reduction of fractions to a common denominator sum=(cd/frc[i].dnm)*frc[i].nmr+(cd/cd0)*sum;//summation gcd=EUCLID_GCD(abs(cd),abs(sum)); sum=sum/gcd; cd=cd/gcd; //reduction of a fraction it=it+sum/cd+frc[i].it; sum=sum%cd; //get integer part } nm=sum; if(it<0&&nm<0) { printf("%lld %lld/%lld",it,nm,cd); }else if(it<0&&nm==0) { printf("%lld",it); }else if(it==0&&nm!=0) { printf("%lld/%lld",nm,cd); }else if(it>0&&nm>0) { printf("%lld %lld/%lld",it,nm,cd); }else { printf("%lld",it); } return 0; } long long EUCLID_GCD (long long a,long long b) { if(b==0)return a; else return EUCLID_GCD(b,a%b); }
原文:https://www.cnblogs.com/wcz-/p/10482107.html