我们可以使用位运算符从十进制转换到除4、8、16等以外的其他进制吗?C.



我们可以使用位运算符从十进制转换到除4、8、16等以外的其他进制吗?我知道如何为4、8、16等等做这件事。但是从十进制到以3为基数,或者以12为基数,我就不知道了。有可能吗?

我想你的问题是在修正从二进制到其他基数的转换。

所有算术运算都可以简化为位运算和移位。这也是CPU在硬件内部所做的。

a + b ==> (a ^ b) + ((a & b) << 1)

右边仍然有一个+在那里,所以你必须一次又一次地应用相同的变换,直到你的左移大于你的整数类型的宽度。或者一点一点地循环。

与两个补数:

-a ==> ~a + 1

如果有+negate就有-*只是一堆移位和添加。/是一堆移位和减法。想想你在学校里是怎么做乘法和长除法的,然后把它降到以2为底。

对于大多数基数来说,用位运算进行数学运算是疯狂的。特别是如果您的代码是从上面的基本操作派生出来的。cpu的加法、子运算和多运算都很好,而且速度更快。但是,如果您想为独立环境(如内核)实现printf(),则可能需要对uint64_t / 10进行划分,这是CPU在硬件中无法完成的。编译器(gcc, clang)也不够聪明,不能很好地做到这一点,它退回到一般的迭代uint64_t / uint64_t长除法算法。

但是除法可以通过乘以逆移几位并将结果移回来来完成。这个方法对于除以10的除法效果很好,你会得到很好的优化代码:

uint64_t divu10(uint64_t n) {
uint64_t q, r;
q = (n >> 1) + (n >> 2);
q = q + (q >> 4);
q = q + (q >> 8);
q = q + (q >> 16);
q = q + (q >> 32);
q = q >> 3;
r = n - (((q << 2) + q) << 1);
return q + (r > 9);
}

这比gcc/clang在编写x / 10时调用的一般uint64_t / uint64_t长除法函数更短,速度更快。

注:(((q << 2) + q) << 1)q * 10。当cpu没有64位整数时,另一个比q * 10更快的按位操作

最新更新