比较没有溢出的分数 我用C++编写代码。我得到了两个分数,a/b和c/d,其中a,b,c,d是int。有人知道一种不溢出a/b>c/d的方法吗。例如,如果我将a,b,c,d设置为小于2147483647的4个最大素数。如何确定a/b>c/d是否为真。我不允许使用int以外的任何其他类型(即,我不能转换为long-long或double)。

比较没有溢出的分数 我用C++编写代码。我得到了两个分数,a/b和c/d,其中a,b,c,d是int。有人知道一种不溢出a/b>c/d的方法吗。例如,如果我将a,b,c,d设置为小于2147483647的4个最大素数。如何确定a/b>c/d是否为真。我不允许使用int以外的任何其他类型(即,我不能转换为long-long或double)。,c++,overflow,fractions,C++,Overflow,Fractions,您可以使用标准算法(比较a*d和b*c),但使用64位乘法以外的其他方法进行乘法。例如,将数字分成16位块,并使用标准的biginteger乘法例程计算结果。您可以使用school长除法获得除数和商,然后继续递归除法,如下面的伪代码所示: bool compare(a,b,c,d) a/b = n + r/b c/d = m + q/d if (n == m) if (r == 0 && q == 0) return false

您可以使用标准算法(比较a*d和b*c),但使用64位乘法以外的其他方法进行乘法。例如,将数字分成16位块,并使用标准的biginteger乘法例程计算结果。

您可以使用school长除法获得除数和商,然后继续递归除法,如下面的伪代码所示:

bool compare(a,b,c,d)
    a/b = n + r/b
    c/d = m + q/d
    if (n == m) 
        if (r == 0 && q == 0) return false
        if (r == 0) return false
        if (q == 0) return true
        if (a < b && c < d)
            if (c/a == d/b && c%a == 0 && d%b == 0) return false
            return !compare(b,r,d,q)  //flip it to continue
    if (n > m) return true       //a/b > c/d
    else if (n < m) return false //a/b < c/d
    else return compare(r,b,q,d) //need to continue comparing
bool比较(a、b、c、d)
a/b=n+r/b
c/d=m+q/d
如果(n==m)
如果(r==0&&q==0)返回false
如果(r==0)返回false
如果(q==0)返回true
if(am)返回true//a/b>c/d
否则如果(n
以下是一种适用于正整数的方法:

bool greaterPositiveFraction(int a,int b,int c,int d);

bool greaterOrEqualPositiveFraction(int a,int b,int c,int d)
{
  if (b == 0) return true;
  if (d == 0) return false;
  if (a/b > c/d) return true;
  if (a/b < c/d) return false;
  return !greaterPositiveFraction(b,a%b,d,c%d);
}

bool greaterPositiveFraction(int a,int b,int c,int d)
{
  if (d == 0) return false;
  if (b == 0) return true;
  if (a/b > c/d) return true;
  if (a/b < c/d) return false;
  return !greaterOrEqualFraction(b,a%b,d,c%d);
}
bool greaterpositiverefraction(inta、intb、intc、intd);
布尔更大或相等正分数(整数a、整数b、整数c、整数d)
{
如果(b==0),则返回true;
如果(d==0)返回false;
如果(a/b>c/d)返回true;
如果(a/bc/d)返回true;
如果(a/b
其思想是,如果整数除法小于或大于,则您知道答案。只有当整数除法得到相同的结果时,这才是棘手的。在这种情况下,您可以只使用余数,然后查看a%b/b>c%d/d。但是,如果b/(a%b)c%d/d,因此我们可以将问题扭转过来,然后再试一次

带负数余数的整数除法有点混乱,但这些问题可以通过以下情况轻松处理:

bool greaterFraction(int a,int b,int c,int d)
{
  if (b<0) { b = -b; a = -a; }
  if (d<0) { d = -d; c = -c; }
  if (a<0 && c<0) return greaterPositiveFraction(-c,d,-a,b);
  if (a<0) return false;
  if (c<0) return true;
  return greaterPositiveFraction(a,b,c,d);
}
bool greaterfract(inta,intb,intc,intd)
{

如果(b像这里这样做std int除法:(参见带余数的整数除法)。逐int除法不会溢出,并且您可以得到商和提醒。现在如果Q1>Q2或Q1 例如,以复数Q1==Q2为例,25/12和44/21,Q1=2和R2=1,Q2=2和R2=2,因此Q1==Q2,你现在需要比较1/12和2/21。现在你做一个公约数是12*21,但你不需要相乘,你只需要比较1*21和2*12。也就是说,你比较(1*21)/(12*21)和(2*12)/(12*21)但由于除数相同,这意味着只比较1*21和2*12

嗯,但是1*21和2*12都可能溢出(如果不是12而是maxint)。好吧,不管怎样,它可能会给出一些想法

为了获得更好的解决方案,只需实现您自己的128位(或N位)整数类。这并不难做到,可能需要半天时间。您只需将64位的高低部分分开,并重载运算符+-*/>(a/b>c/d)可以部分地写为在许多情况下避免算术,然后在其余情况下避免算术溢出和下溢。请注意,最后一个案例留给读者作为练习

bool fractioncompare(int a, int b, int c, int d) {
    bool cd_negative = (c < 0 && d > 0) || (c > 0 && d < 0);
    bool ab_negative = (a < 0 && b > 0) || (a > 0 && b < 0);

    // if c/d negative and a/b positive then a/b is larger
    if(cd_negative && !ab_negative) return true;

    // if c/d postive and a/b negative then a/b is not larger
    if((!cd_negative && ab_negative) return false;

    bool both_negative = cd_negative && ab_negative;

    // limited cases were a/b > c/d can be determined without needing to 
    // do arithmetic calculations (so no risk of overflow / underflow)
    if(a > c && b < d) return !both_negative;
    if(a < c && b > d) return both_negative;

    int ab = a/b;
    int cd = c/d;

    bool no_trunc = a % b && c % d;
    if(no_trunc) return ab > cd;

    // No risk of overflow with divide and skipping the equal case avoids 
    //truncation issues
    if(ab > cd) return true;
    if(ab < cd) return false;

    // truncation may mean ab and cd aren't actually equal so do some
    // comparisons on differences to determine the result
    if(!both_negative)
    {
        // use subtraction only to avoid overflow
        if(ab == 0) return (b-(b-a) > d-(d-c));
        else return (b-(b-a) < d-(d-c));
    }
    else
    {
        // TODO subtract values with same sign and add with 
        // different signs and compare appropriately to determine result
    }

}
bool fractioncompare(整数a、整数b、整数c、整数d){
boolcd|u负值=(c<0&&d>0)|(c>0&&d<0);
布尔ab_负=(a<0&&b>0)| |(a>0&&b<0);
//如果c/d为负,a/b为正,则a/b较大
if(cd_负值&!ab_负值)返回true;
//如果c/d为正,a/b为负,则a/b不较大
如果(!cd_负值和&ab_负值)返回false;
bool双负=cd双负和ab双负;
//有限的病例a/b>c/d可以确定,无需
//进行算术计算(因此没有溢出/下溢的风险)
如果(a>c&&bd)同时返回两个负;
int ab=a/b;
int cd=c/d;
bool no_trunc=a%b&c%d;
如果(否)返回ab>cd;
//使用除法和跳过相等大小写避免了溢出风险
//截断问题
如果(ab>cd)返回true;
如果(abd-(d-c));
否则返回(b-(b-a)
标准方法是确定ad是否大于bc。@LuchianGrigore:这将溢出,因为小于2147483647的两个最大素数的乘积肯定大于2147483647。如果a/b==c/dIn函数greaterEqualPositiveFraction调用greaterFraction不应该是greaterPositiveFraction吗?@2501:已修复。谢谢,(n==m)检查似乎不正确。如果r/b>q/d,可能仍然是a/b>c/d。在某些情况下似乎是一个无限递归。例如,a=1,b=2,c=1,d=3。添加了这种情况。运行直到a/b和c/d都<1,并翻转以允许计算继续。对于a=1,b=2,c=1,d=2,将返回真值。捕捉得好!在任何一个除法w中都没有截断的情况未处理。当发生这种情况时,可以直接准确地比较结果整数。代码更新。