我用C ++编写代码。我得到2个分数,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)。
答案 0 :(得分:7)
这是一种适用于正整数的方法:
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);
}
这个想法是,如果整数除法更小或更大,那么你知道答案。如果整数除法给出相同的结果,那将是棘手的。在这种情况下,您可以使用余数,并查看%b / b&gt; C%d / d。但是,我们知道a%b / b> c%d / d,如果b /(a%b)< d /(c%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);
}
答案 1 :(得分:4)
您可以执行标准算法(将a * d与b * c进行比较),但使用64位乘法以外的其他方法进行乘法运算。就像将数字划分为16位块并使用标准的大整数乘法例程来计算结果。
答案 2 :(得分:0)
您可以使用学校长除法来获得被除数和商,并继续递归分割,如下面的伪代码:
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
答案 3 :(得分:0)
就像这样执行std int division:http://en.wikipedia.org/wiki/Division_algorithm(参见带余数的整数除法(unsigned))。 Div int by int不会溢出,你得到商和提醒。现在,如果Q1> Q2或Q1&lt; Q2很明显,如果Q1 == Q2,则比较R1 / b和R2 / d。
E.g。取复数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位部分分离并重载运算符+ - * /&gt;&gt;&lt;&lt;。
答案 4 :(得分:0)
(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
}
}