【问题标题】:Code performance between if else statements and length of stringif else 语句和字符串长度之间的代码性能
【发布时间】:2012-10-03 02:31:17
【问题描述】:

我正在编写代码,该代码从用户那里获取一个数字并以字符串形式以字母形式打印出来。我想知道,有 if 语句,如

if (n < 100) {
    // code for 2-digit numbers
} else if (n < 1000) {
    // code for 3-digit numbers
} // etc..

或将数字放入字符串中并获取其长度,然后将其作为字符串处理。

代码是用 C++ 编写的。

【问题讨论】:

  • 将boost::lexical_cast 用于此类容易出错的任务。在你测量之前不要担心这里的性能。当很明显这会影响速度时,仍然是时候进行优化了。
  • 这会快得多,但这是编写代码的一种糟糕方式。仅当您迫切需要更快的速度时才应考虑它。
  • @Jon:你是在暗示转换为std::string 是更好的代码编写方式吗?
  • @phresnel:我没有暗示任何事情。我写的就是我的意思,不多也不少。

标签: c++ string performance if-statement string-length


【解决方案1】:

当然if-else 会更快。

要比较两个数字,您只需按位比较它们(有不同的方法可以做到这一点,但这是一个非常快速的操作)。

要获得字符串的长度,您需要创建字符串,将数据放入其中并以某种方式计算长度(也可以有不同的方法,最简单的方法是计算所有符号)。当然,这需要更多的时间。

在一个简单的例子中,虽然您不会注意到任何区别。人们常常关心这些事情(无意冒犯),这常常让我感到惊讶。如果代码将在0.003 秒内执行而不是在0.001 秒内执行,这对您没有任何影响...只有在您知道确实如此之后,您才应该进行此类低级优化位置是您的应用程序的瓶颈,当您确定可以将性能提高相当多时。

【讨论】:

    【解决方案2】:

    在您测量到这确实是一个瓶颈之前,不要担心性能。

    也就是说,以下应该更快(为了便于阅读,我们假设您使用的类型介于 0 和 99999999 之间):

    if (n < 10000) {
        // code for less or equal to 4 digits
        if (n < 100)
        {
           //code for less or equal to 2 digits
           if (n < 10)
              return 1;
           else
              return 2;
        }
        else
        {
           //code for over 2 digits, but under or equal to 4
           if (n>=1000)
              return 4;
           else
              return 3;
        }
    } else {
        //similar
    } // etc..
    

    基本上,它是二分搜索的一种变体。在最坏的情况下,这将采用 O(log(n)) 而不是 O(n) - n 是最大位数。

    【讨论】:

    • 虽然复杂性更好,但如今人们经常减少分支嵌套以帮助现代 CPU 进行预测。
    【解决方案3】:

    string 变体会更慢:

    std::stringstream ss;       // allocation, initialization ...
    ss << 4711;                 // parsing, setting internal flags, ...
    std::string str = ss.str(); // allocations, array copies ...    
    
    // cleaning up (compiler does it for you) ...
    str.~string();
    ss.~stringstream();         // destruction ...
    

    ... 表示还有更多事情发生。

    一个紧凑(适合缓存)循环(适合分支预测)可能是您想要的:

    int num_digits (int value, int base=10) {
        int num = 0;
        while (value) {
            value /= base;
            ++num;
        }
        return num;
    }
    
    int num_zeros (int value, int base=10) {
        return num_decimal_digits(value, base) - 1;
    }
    

    视情况而定,因为它对缓存和预测友好,这可能比基于关系运算符的解决方案更快。

    模板化变体使编译器能够为您的部门进行一些微优化:

    template <int base=10>
    int num_digits (int value) {
        int num = 0;
        while (value) {
            value /= base;
            ++num;
        }
        return num;
    }
    

    【讨论】:

      【解决方案4】:

      答案很好,但请考虑一下相对时间。

      即使是你能想到的最慢的方法,程序也可以在几分之一秒内完成,比如 100 微秒。

      与您可以想象的最快的用户进行权衡,谁可以在 500 毫秒内输入数字,谁可以在另外 500 毫秒内读取输出,然后再执行下一步操作。

      好的,机器在 1000 毫秒内基本上什么都不做,而在中间它必须疯狂地运行 100 微秒,因为毕竟我们不希望用户认为程序很慢 ;-)

      【讨论】:

        猜你喜欢
        • 2018-03-09
        • 2017-10-04
        • 2016-05-07
        • 2021-02-23
        • 2013-11-26
        • 1970-01-01
        • 2019-02-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多