如何消除"a/b>c/d"等代码内的除法?

How to eliminate division inside code like "a/b>c/d"?

比如我不想在"a/b==c/d"除法,我可以改写成"ad==bc".

但"a/b>c/d"并不总是="ad>bc",例如:

a=20, b=5, c=9,d=3 : a/b>c/d 为真且 ad>bc是真的

但是

a=-20, b=-5, c=9,d=3 : a/b>c/d 为真但 ad>bc 为假

开始找patten,好像(不知道对不对):

如果b和d同号,a/b>c/d = ad > bc

如果 b 和 d 的符号不同,a/b > c/d = ad < bc

如果我将 "a/b>c/d" 重写为

(( (b>0 && d>0 || b<0 && d<0) && a*d>b*c) || ( ((b>0 && d<0) || b<0 && d>0) && a*d<b*c)

,它需要输入更多的字符,而且每个变量我需要输入超过 1 次,如果我想更改为

,这种形式很难维护
a/b>=c/d 

a/b<c/d

有什么方法可以更简单地消除a/b>c/d中的除法吗?

当您将不等式的两边都乘以某个非零数 v 时,如果 v 为负,您必须反转不等式的方向。

所以在你的情况下你乘以 b*d 所以

if (a/b > c/d) {
 ...
}

等同于

v = b * d;
if(v==0) {
  error
}

if ( ( (v>0) && (a*d > c*b) ) || 
     ( (v<0) && (a*d < c*b) ) ) {
   ...
}

如果您不关心您使用的是 > 还是 >=,或者关心 v==0 的处理,您可以将其重写为

if ( (v>0) ^ (a*d > c*b ) ) {
  ...
}

如果 abcd 是浮点数,则需要进一步考虑,因为您需要考虑正无穷大和负无穷大的行为,带符号的零和 "not a number" 值。

你可以改写为:

a*d*b*d > b*c*b*d

这样,如果 b 和 d 的符号不同,则 b*d 将为负数,比较结果将以正确的方式翻转。但是要小心溢出。要使代码等效于 a/b > c/d,您还需要检查 b 或 d 是否为零。

可能你可以通过按位运算得到b和d的符号,然后将"a/b>c/d"改写为

(((b>>31)&1) ^ ((d>>31)&1)) ^ (ad > bc)

相当于

((b>0) ^ (d>0)) ^ (ad > bc)

假设 b 和 d 是 32 位整数