为了通过舍入对无符号值进行右移,以下函数对我有用:
unsigned rshift_round_down(unsigned x, unsigned a) {
return x >> a;
}
unsigned rshift_round_up(unsigned x, unsigned a) {
return (x >> a) + ((x & ((1 << a) - 1)) != 0);
}
unsigned rshift_round_halfway(unsigned x, unsigned a) {
return (x >> a) + ((x >> (a - 1)) & 1);
}
unsigned rshift_round_towards_even(unsigned x, unsigned a) {
return (x >> a) + ((x >> (a - ((x & ((1 << a) - 1)) != 1 << (a - 1)))) & 1);
}
是否有更简单但等效的 rshift_round_towards_even 实现?
输入和输出示例:
现有代码存在问题
当 1 移入符号位时,1 << a
是未定义行为 (UB)。 使用1u << a
。
rshift_round_halfway(x , 0)
是 UB,因为 (x >> (a - 1))
是负位移。
未经测试的替代品
rshift_round_towards_even()
也许有问题 - 稍后会评论 - GTG。
unsigned rshift_round_towards_even_alt(unsigned x, unsigned a) {
unsigned shifted_lsbit_mask = 1u << a;
unsigned bits_shifted_out_mask = shifted_lsbit_mask - 1u;
unsigned bits_shifted_out = bits_shifted_out_mask & x;
unsigned is_even = !(shifted_lsbit_mask & x);
unsigned carry = (bits_shifted_out + is_even) > (lsbit_shifted_out_mask >> 1);
return (x >> a) + carry;
}