作者:一切近乎完美 | 来源:互联网 | 2023-05-17 18:06
主要问题是运算过程中的溢出,为防止溢出必须用简约式的运算过程,比如若case是512163210737418243276810737418241073741824107374
主要问题是运算过程中的溢出,为防止溢出必须用简约式的运算过程,比如若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
#include
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)
{
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)
{
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);
}