常数乘法可以用左移,加法和减法代替:
int multiply10(int x){
return (x<<3)+(x<<1);
}
int multiply31(int x){
return (x<<5)-x;
}
所以我想,为什么不将它扩展到更大的数字?但一个简单的总和很慢:
int multiply52429(int x){
return (x<<15)+(x<<14)+(x<<11)+(x<<10)+(x<<7)+(x<<6)+(x<<3)+(x<<2)+x;
}
所以我们做了一些变数:
int multiply52429(int x){
int y = (x<<1)+x;
y = (y<<4)+y;
y = (y<<8)+y;
return (y<<2)+x;
}
现在我们问,如何为这样一个最佳的函数生成代码?*
只有常数的加法,减法和左移将计入总数,所有的“成本”均为1,其他一切都是免费的。
* AST,汇编,无论如何,任何可以转换的格式都可以。重要的是最佳乘法算法,而不是代码格式化。
一些可能接近最佳的例子:
int multiply1671523a(int x){
int x3 = (x<<1)+x;
int x99 = (x3<<5)+x3;
return (x99<<15)-(x3<<19)+(x<<8)+x99;
}
int multiply1671523b(int x){
int x3 = (x<<1)+x;
int x51 = (x3<<4)+x3;
return (x51<<15)+(x<<8)+(x3<<4)+x51;
}
int multiply1671523c(int x){
int x3 = (x<<1)+x;
return (x3<<19)+(x3<<15)+(x<<8)+(x3<<5)+x3;
}
int multiply220374293(int x){
int x5 = (x<<2)+x;
int x21 = (x5<<2)+x;
int x105 = (x21<<2)+x21;
return (x105<<21)+(x21<<13)+(x5<<8)+x21;
}
请注意上一个示例中的重用。
这没有实际用途(乘法总是更快,如果它在某种程度上较慢,编译器会处理它),但我认为这是一个很好的问题并且很好奇。什么样的算法可以解决它,以及什么时间复杂度?