相关文章我以前也发过一次,但是那种写法显然不够简洁,今天意外又发现了一种:
int log_2(int x) {
float f = x;
return (*(int*)&f >> 23) - 0x7f;
}
benchmark下来跟以前那种差距不大,下面简单描述一下原理:
根据 IEEE 754,float
类型在内存中占32bit
,依次存储1bit
符号位、8bit
阶码和22bit
尾数。这里阶码就是我们所需要的,另外既然取以2为底的对数那么真数必然非负,所以符号位可以不考虑,只要进行一次移位操作就可以得到阶码,根据标准阶码减去0x7f
就是我们所需。
另外,上面的代码中来回用指针的目的只是把float
类型的数据一个比特不动地强制转换到int
,如果你认为其不优雅,可以使用以下c++20
中新加入的内容实现:
#include <bit>
int log_2(int x) {
float f = x;
return (std::bit_cast<int>(f) >> 23) - 127;
}