You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求无符号数右移向偶舍入函数的简洁等价实现

无符号数带舍入右移:向偶数舍入的简洁等价实现

背景与问题

对无符号数执行带舍入的右移操作时,已有以下可行实现:

// 向下舍入右移
unsigned rshift_round_down(unsigned x, unsigned a) {
  return x >> a;
}

// 向上舍入右移
unsigned rshift_round_up(unsigned x, unsigned a) {
  return (x >> a) + ((x & ((1U << a) - 1)) != 0);
}

// 中间值向上舍入右移
unsigned rshift_round_halfway(unsigned x, unsigned a) {
  if (a == 0) return x;
  return (x >> a) + ((x >> (a - 1)) & 1);
}

// 向偶数舍入右移(原实现)
unsigned rshift_round_towards_even(unsigned x, unsigned a) {
  if (a == 0) return x;
  return (x >> a) + ((x >> (a - ((x & ((1U << a) - 1)) != 1 << (a - 1)))) & 1);
}

现询问:是否存在更简洁但功能完全等价的rshift_round_towards_even实现?

注:参数a的取值范围为 0 <= a && a < sizeof(unsigned) * 8,无需支持超出该范围的取值。

示例输入输出

  • rshift_round_towards_even(60, 2) == 15
  • rshift_round_towards_even(61, 2) == 15
  • rshift_round_towards_even(62, 2) == 16 (中间值向偶数舍入,结果向上)
  • rshift_round_towards_even(63, 2) == 16
  • rshift_round_towards_even(64, 2) == 16
  • rshift_round_towards_even(65, 2) == 16
  • rshift_round_towards_even(66, 2) == 16 (中间值向偶数舍入,结果向下)
  • rshift_round_towards_even(67, 2) == 17
  • rshift_round_towards_even(68, 2) == 17
  • rshift_round_towards_even(69, 2) == 17
  • rshift_round_towards_even(70, 2) == 18 (中间值向偶数舍入,结果向上)
  • rshift_round_towards_even(71, 2) == 18
  • rshift_round_towards_even(72, 2) == 18
  • rshift_round_towards_even(73, 2) == 18

简洁等价实现

有,基于向偶数舍入的核心规则:

  1. 若舍去部分大于2^(a-1),则进位;
  2. 若舍去部分小于2^(a-1),则不进位;
  3. 若舍去部分恰好等于2^(a-1)(中间值),仅当右移后的结果为奇数时进位,否则不进位。

易读版实现

unsigned rshift_round_towards_even(unsigned x, unsigned a) {
  if (a == 0) return x;
  const unsigned mask = (1U << a) - 1;
  const unsigned lower_bits = x & mask; // 被舍去的低a位
  const unsigned upper_bits = x >> a;  // 右移后的高位部分
  // 判断是否需要进位
  const int need_round = (lower_bits > (1U << (a-1))) || 
                         (lower_bits == (1U << (a-1)) && (upper_bits & 1));
  return upper_bits + need_round;
}

紧凑位运算版

如果追求代码紧凑,可将逻辑合并为一行(可读性稍降,但功能完全等价):

unsigned rshift_round_towards_even(unsigned x, unsigned a) {
  return a ? (x >> a) + (((x >> (a-1)) & 1) & ((x & ((1U << a)-1)) != (1U << (a-1)) || ((x >> a) & 1))) : x;
}

高效运算版

利用无符号数加法特性,还能写出更高效的实现:

unsigned rshift_round_towards_even(unsigned x, unsigned a) {
  if (a == 0) return x;
  const unsigned half = 1U << (a-1);
  const unsigned mask = (1U << a) - 1;
  // 先按中间值向上舍入,再修正中间值时的偶数舍入规则
  return (x + half - 1) >> a - ((x & mask) == half && !((x >> a) & 1));
}

以上实现均与原函数功能完全一致,但代码更简洁、可读性更强。


内容的提问来源于stack exchange,提问作者pts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 13:44:53