GCD LCM 最大公约数 最小公倍数 分数模板 (防溢出优化完成)

自己写的一个分数模板,在运算操作时进行了防溢出的优化:

ll gcd(ll a, ll b) {
    return b ? gcd(b, a%b) : a;
}
 
ll lcm(ll a, ll b) {
    return a / gcd(a,b) * b;
}
 
struct divi {
    ll a = 0,b = 1;
};
 
divi simdiv(divi a) {
    ll i;
    divi divn = a;
    ll k = gcd(a.a,a.b);
    divn.a /= k;
    divn.b /= k;
    if(divn.b < 0) {
        divn.a = -divn.a;
        divn.b = -divn.b;
    }
    return divn;
}
 
divi plusdiv(divi i,divi j) {
    divi a = simdiv(i);
    divi b = simdiv(j);
    divi dn;
    dn.b = lcm(a.b,b.b);
    dn.a = a.a*(dn.b/a.b)+b.a*(dn.b/b.b);
    return simdiv(dn);
}
 
divi minusdiv(divi i,divi j) {
    divi a = simdiv(i);
    divi b = simdiv(j);
    divi dn;
    dn.b = lcm(a.b,b.b);
    dn.a = a.a*(dn.b/a.b)-b.a*(dn.b/b.b);
    return simdiv(dn);
}
 
divi muldiv(divi i, divi j) {
    divi a = simdiv(i);
    divi b = simdiv(j);
    divi dn;
    ll chu1 = gcd(a.a,b.b);
    ll chu2 = gcd(a.b,b.a);
    dn.b = (a.b/chu2) * (b.b/chu1);
    dn.a = (a.a/chu1) * (b.a/chu2);
    return simdiv(dn);
}
 
divi divdiv(divi i,divi j) {
    divi a = simdiv(i);
    divi b = simdiv(j);
    divi dn;
    ll chu1 = gcd(a.a,b.a);
    ll chu2 = gcd(a.b,b.b);
    dn.b = (a.b / chu2) * (b.a / chu1);
    dn.a = (a.a / chu1) * (b.b / chu2);
    return simdiv(dn);
}
 
int cmpdiv(divi i,divi j) {    //a>b返回1, a=b返回0, a<b返回-1, 无法比较返回INF
    divi a = simdiv(i);
    divi b = simdiv(j);
    if(a.b == 0 || b.b == 0) {
        if(a.b == 0 && b.b == 0)    return INF;
        else {
            if(a.b == 0) {
                if(a.a > 0)    return 1;
                if(a.a < 0)    return -1;
                if(a.a == 0)    return INF;
            } else {
                if(b.b == 0) {
                    if(b.a > 0)    return -1;
                    if(b.a < 0)    return 1;
                    if(b.a == 0)    return INF;
                }
            }
        }
    } else {
        ll di = lcm(a.b,b.b);
        ll a1 = a.a * (di / a.b);
        ll a2 = b.a * (di / b.b);
        if(a1 > a2)    return 1;
        if(a1 == a2)    return 0;
        if(a1 < a2)    return -1;
    }
}
 
double valueofdiv(divi a) {
    if(a.a == 0)    return 0;
    if(a.b == 0) {
        if(a.a >= 0)    return (double)INF;
        if(a.a < 0)    return -(double)INF;
    }
    return (double)a.a/(double)a.b;
}

测试代码:

divi a,b;
while(1==1) {
    scanf("%lld%lld",&a.a,&a.b);
    scanf("%lld%lld",&b.a,&b.b);
    printf("+: %lld/%lld
",plusdiv(a,b).a,plusdiv(a,b).b);
    printf("-: %lld/%lld
",minusdiv(a,b).a,minusdiv(a,b).b);
    printf("*: %lld/%lld
",muldiv(a,b).a,muldiv(a,b).b);
    printf("/: %lld/%lld
",divdiv(a,b).a,divdiv(a,b).b);
    printf("cmp: %d
",cmpdiv(a,b));
    printf("value: %lf %lf
",valueofdiv(a),valueofdiv(b));
}
原文地址:https://www.cnblogs.com/zinyy/p/9139106.html