C ++什么是更快:if还是length?

时间:2016-03-13 19:57:50

标签: c++ performance

我有一个整数,数字代表输出给用户(类似错误输出)

如果整数小于100则是错误,因此字体的样式为"错误样式"。

如果整数大于100则是成功消息,因此字体的样式为"成功风格",

我想扩展这个,例如为超过1000等的所有整数添加新样式...

目前,我这样检查:

if (m_errorNumber < 100) {
    errorColor.setColor(255, 0, 0, 255);
} else {
    errorColor.setColor(0, 255, 0, 255);
}

现在我的理由是,如果我可以加快速度,例如检查,如果整数的长度在1到2或3或4之间等等......

所以我的详细问题是,如何尽可能快地找到合适的案例?

1 个答案:

答案 0 :(得分:2)

  

所以我的详细问题是,如何尽可能快地找到合适的案例?

你很少“如果小于......其他”规则,所以性能不是问题,没有办法,也没有必要提高速度。一系列if可以很好地完成工作。当然,除非你真的测量了速度并发现了瓶颈。

然而,从计算机科学的角度来看,有可能提出一种解决方案,该解决方案提供更好的计算复杂性,使得必要的比较操作的数量将按比例减少 n 得到,即你拥有的规则越多。

我们来看看。您的“如果小于......其他”规则构成某些范围,并且if的实体都使用不同的参数执行相同的操作。

此场景可以描绘为一个映射,其中每个范围的结尾都映射到一个参数集。在C ++中:

struct ColorArguments { int a; int b; int c; int d; };
std::map<int, ColorArguments> ranges;

然后按如下方式填写地图:

ranges[100] = { 255, 0 , 0 , 255 };
ranges[1000] = { 0, 255 , 0 , 255 };
ranges[std::numeric_limits<int>::max()] = { 0, 0, 0, 255 };

事实上,不应该填写它,而应该初始化它并使其const

std::map<int, ColorArguments> const ranges = {
    { 100,                             { 255, 0   , 0, 255 } },
    { 1000,                            { 0,   255 , 0, 255 } },
    { std::numeric_limits<int>::max(), { 0,   0,    0, 255 } }
};

最后,upper_bound成员函数可用于为您提供适当的ColorArguments个对象。该函数将迭代器返回到第一个元素,该元素的键大于指定值。

例如,在此地图中,搜索500将为您提供指向具有键1000的元素的指针,因为1000是第一个大于500的键。

upper_bound具有对数复杂度,这比原始if-else链的线性复杂度更好,更好,尽管潜在的编译器优化可能会将线性代码转换为更复杂的东西。

auto const iter = ranges.upper_bound(m_errorNumber);
auto const& colors = iter->second;

请注意,如果使用std::numeric_limits<int>::max()(您机器上的最大int)作为地图中的键,可以避免upper_bound返回ranges.end()的特殊处理(除非输入本身可能是std::numeric_limits<int>::max(),在这种情况下你需要一些特殊的处理。)

以下是一个完整的例子:

#include <map>
#include <limits>
#include <iostream>

struct ColorArguments { int a; int b; int c; int d; };

void setColor(int a, int b, int c, int d)
{
    std::cout << a << ", " << b << ", " << c << ", " << d << "\n";
}

int main()
{
    std::map<int, ColorArguments> const ranges = {
        { 100,                             { 255, 0   , 0, 1 } },
        { 1000,                            { 0,   255 , 0, 2 } },
        { std::numeric_limits<int>::max(), { 0,   0,    0, 3 } }
    };

    int const errorNumber = 500;

    auto const iter = ranges.upper_bound(errorNumber);

    setColor(
        iter->second.a,
        iter->second.b,
        iter->second.c,
        iter->second.d
    );
}

除了算法复杂性之外,该解决方案还将静态的,硬编码的if-else逻辑转换为数据,可以在运行时动态修改或读取。即使您不在此处使用它来解决您的具体问题,也应牢记这一点。