如何优化以下内容(将算法转换为逐位操作)?
优化:
int A = B * 4
int A = B * 72
int A = B % 1
int A = B % 16
int A = (B + C) / 2
int A = (B * 3) / 8
int A = (B % 8) * 4
在面试中看到这些问题。
答案 0 :(得分:4)
面试官可能正在寻找你能够在误导的观念下将算术转换为按位运算,这种观念会更快。编译器将执行优化,因此您无需优化。如果您没有优化编译器,那么正确的做法是分析您的代码以查看性能瓶颈所在并修复它们。算术不太可能是你的性能瓶颈。
那就是说,这可能是面试官正在寻找的:
B * 4
,可以使用位移操作(例如B << 2
)执行乘以2的幂。这实现了相同的结果。B * 72
,实际上是B * 8 * 9
,即B * 2^3 * (2^3 + 1) = (B*2^6) + (B*2^3)
。同样,解决方案是找到2的幂并使用位移操作写入它们。 (B << 6) + (B << 3)
与B * 72
B % 16
,始终是0-15范围内的数字(如果B为正),这是要求整数的最后4位,并且可以使用位掩码找到:{{1} }。请注意,在每种情况下,代码的含义都更难以遵循。 B & 0xF
比B * 72
更容易阅读。尝试挑选代码性能而不实际分析任何内容的过程称为过早优化。如果您对代码进行概要分析并发现它的性能瓶颈确实是这些数学运算,那么您可以用优化的形式重写它们,但是您必须记录代码的含义,以便下一个查看它的人理解为什么代码如此混乱
我会注意到,如果我是面试官提出这个问题(我不会问这个问题),我宁愿回答“让编译器进行优化”,只是盲目地找到表达算法的按位方式
答案 1 :(得分:1)
所有这些计算都可以通过位移完成;但是,这只适用于正数。我们需要有一个负面输入的特殊情况,因为面试官没有指定哪个!
4 = 2 2 的乘法可以通过左移2位来完成。
int A = (B < 0) ? -((-B) << 2)) : B << 2;
如果我们直接对它进行转换,负数会溢出并给出错误的结果,所以我们在减去它时操作。
72 = 64 + 8 = 2 6 + 2 3 。因此:
int A = (B < 0) ? -(((-B) << 6) + ((-B) << 3)) : (B << 6) + (B << 3)
C ++标准中的负数模数相当于:
neg_number % N = -((-neg_number) % N);
(自己测试)
但这对模数没有影响1!因此int A = 0;
使用AND(&
)作为Welbog说:
int A = (B < 0) ? -((-B) & 0xF) : B & 0xF;
按照之前所说的相同,但总和;使用右移1:
int A = (B + C < 0) ? -((-(B+C)) >> 1) : (B + C) >> 1;
int A = (B < 0) ? -(((-B) << 1 - B) >> 3) : (B << 1 + B) >> 3;
int A = (B < 0) ? -(((-B) & 7) << 2) : (B & 7) << 2;