问题描述
这不是 FizzBuzz 代码中关于如何处理重复 if 语句的典型争论。我认为这是个人喜好问题。
我是来询问重复数学运算的选择。
通常对 FizzBuzz 代码的解决方案是在每次迭代中使用模数运算符。但是,我担心它对性能的影响。
据我所知,取模运算符与除法运算符紧密相连,与简单的自增和自减运算符相比,具有相当大的性能开销。
另外,我不相信编译器有能力分析和优化循环中模运算符的使用。
因此,我给出了仅使用简单递减运算符的替代解决方案。以下代码是用C++编写的。
我寻求洞察我的方法是否会带来性能优势,或者它是否实际上是一个降低性能的可怕想法。
如果还有其他方法可以进一步优化 FizzBuzz 代码。 (我认为在一个修改过的 FizzBuzz 拼图中有很多案例要比较,查找表可能更可取)
典型的 FizzBuzz 解决方案。
for (unsigned int i = 1; i <= 1000000; ++i) {
if (!(i % 15))
std::cout << "FizzBuzz\n";
else if (!(i % 3))
std::cout << "Fizz\n";
else if (!(i % 5))
std::cout << "Buzz\n";
else
std::cout << i << '\n';
}
我优化的代码。
static const unsigned int fa {3};
static const unsigned int fb {5};
unsigned int a {fa};
unsigned int b {fb};
for (unsigned int i = 1; i <= 1000000; ++i) {
--a,--b;
if (!a && !b) {
a = fa;
b = fb;
std::cout << "FizzBuzz\n";
} else if (!a) {
a = fa;
std::cout << "Fizz\n";
} else if (!b) {
b = fb;
std::cout << "Buzz\n";
} else {
std::cout << i << '\n';
}
}
解决方法
在模数情况和递减情况下,运行时间将由流输出决定。即使不考虑 I/O,条件(将很难预测)的贡献也远远超过算术。最后,整数除法或模数除以常数非常快,因为它是通过特殊的乘法例程而不是 DIV 实现的。
在某些情况下,用有条件设置的计数器替换模数会更快。这种情况不是其中之一。