FizzBu​​zz 优化 |模数与递减运算符性能

问题描述

这不是 FizzBu​​zz 代码中关于如何处理重复 if 语句的典型争论。我认为这是个人喜好问题。

我是来询问重复数学运算的选择。

通常对 FizzBu​​zz 代码解决方案是在每次迭代中使用模数运算符。但是,我担心它对性能的影响。

据我所知,取模运算符与除法运算符紧密相连,与简单的自增和自减运算符相比,具有相当大的性能开销。

另外,我不相信编译器有能力分析和优化循环中模运算符的使用。

因此,我给出了仅使用简单递减运算符的替代解决方案。以下代码是用C++编写的。

我寻求洞察我的方法是否会带来性能优势,或者它是否实际上是一个降低性能的可怕想法。

如果还有其他方法可以进一步优化 FizzBu​​zz 代码。 (我认为在一个修改过的 FizzBu​​zz 拼图中有很多案例要比较,查找表可能更可取)


典型的 FizzBu​​zz 解决方案。

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 实现的。

在某些情况下,用有条件设置的计数器替换模数会更快。这种情况不是其中之一。