乘以 0.3 与乘以 (0.3*2^n),然后除以 2^n 相同。第二阶段相当于n右移。
但是n 的最佳值是多少?
要找到它,请取最大整数并找到n 的最大值,这样您就可以乘以(0.3*2^n) 而不会溢出。 64位无符号整数,最大值4096,需要
0.3*2^n <= 2^(64-12)
或
0.3 <= 2^(64-12-n)
当 RHS 等于 0.5 时,这个不等式最大 n,所以
2^-1 = 2^(64-12-n)
所以-1 = 64-12-n,n = 64-12+1 = 53。
所以答案是乘以2^53*0.3,然后右移53,即
/* designed to work with input values 0 .. 4096 only */
uint64_t
multiplyby0_3 (uint64_t x)
{
return (x * 2702159776422297ULL) >> 53;
}
检查没有溢出,我们有最好的n,来自bc:
2702159776422297*4096 = 11068046444225728512
2^64 = 18446744073709551616
IE它不会溢出,但如果我们再次将它乘以2,它就会溢出。
对于 32 位整数,答案是乘以 2^21*0.3 然后右移 21,即
/* designed to work with input values 0 .. 4096 only */
uint32_t
multiplyby0_3 (uint32_t x)
{
return (x * 629146U) >> 21;
}
最后,您可以通过查看乘法器中的二进制1 将任何乘法分解为多个加法。所以你允许 'scaling' 我认为这意味着乘法。如果没有,这里是 32 位版本(留给读者练习的 64 位版本)利用了 629146 是 10011001100110011010 的事实(由于重复出现二进制分数,这是一个简洁的模式)。我们将反过来使用10011001100110011001。
/* designed to work with input values 0 .. 4096 only */
uint32_t
multiplyby0_3 (uint32_t x)
{
uint32_t y;
x += x<<3; /* * 1001 */
y = x<<4 + x; /* * 10011001 */
y += y<<8; /* * 1001100110011001 */
y += x<<16; /* * 10011001100110011001 */
return y >> 21;
}