C中四舍五入的有符号整数除法

fea*_*ool 6 c signed integer-division

我想计算 x/y,其中 x 和 y 都是有符号整数,并将结果四舍五入到最接近的整数。具体来说,我想要一个rquotient(x, y)仅使用整数算术的函数,以便:

ASSERT(rquotient(59, 4) == 15);
ASSERT(rquotient(59, -4) == -15);
ASSERT(rquotient(-59, 4) == -15);
ASSERT(rquotient(-59, -4) == 15);

ASSERT(rquotient(57, 4) == 14);
ASSERT(rquotient(57, -4) == -14);
ASSERT(rquotient(-57, 4) == -14);
ASSERT(rquotient(-57, -4) == 14);
Run Code Online (Sandbox Code Playgroud)

我已经向 SO 寻求解决方案,并发现以下内容(每个都有自己的缺点):

fea*_*ool 5

如果你知道x并且y两者都是积极的:

int rquotient_uu(unsigned int x, unsigned int y) {
  return (x + y/2) / y;
}
Run Code Online (Sandbox Code Playgroud)

如果你知道y是积极的:

int rquotient_su(int x, unsigned int y) {
  if (x > 0) {
    return (x + y/2) / y;
  } else {
    return (x - y/2) / y;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果两者都签名:

int rquotient_ss(int x, int y) {
  if ((x ^ y) >= 0) {            // beware of operator precedence
    return (x + y/2) / y;        // signs match, positive quotient
  } else {
    return (x - y/2) / y;        // signs differ, negative quotient
  }
}
Run Code Online (Sandbox Code Playgroud)

如果你真的想让未来的自己感到困惑或沉迷于编程高尔夫,请抵制这样写的冲动:;)

int rquotient_ss(int x, int y) {
  return (x + (((x^y)>=0)?y:-y)/2)/y;
}
Run Code Online (Sandbox Code Playgroud)

  • 只是要小心其中一些计算中的“int”溢出。 (4认同)
  • 迂腐一点,可以做“((unsigned)x^(unsigned)y)”。 (2认同)
  • 不过,当 x == y 时,“rquotient_ss”似乎给出了[错误的结果](https://wandbox.org/permlink/wmUftW57mrhUXO79) (0)。我认为条件应该是 `(x ^ y) >= 0` (2认同)