L1-009 N个数求和

主要问题是运算过程中的溢出,为防止溢出必须用简约式的运算过程,比如若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);
}

 

posted @ 2019-03-06 11:16  王纯真  阅读(198)  评论(0编辑  收藏  举报