如何提高逗号格式数字的性能

How can I improve formatting number with commas performance?

本文关键字:数字 性能 格式 何提高      更新时间:2023-10-16

我使用以下方法用逗号格式化数字:

template<class T>
static std::string FormatNumberWithCommas(T value, int numberOfDecimalPlaces = 0)
{
    std::stringstream ss;
    ss.imbue(std::locale(""));
    ss.precision(numberOfDecimalPlaces);
    ss << std::fixed << value;
    return ss.str();
}

评测表明,相对于其他代码,此方法需要花费大量时间。具体来说,探查器已识别出以下行:

ss.imbue(std::locale(""));

在这里面,我相信std::locale("")需要很长时间。如何提高此方法的性能?如果它需要使用字符串流以外的东西,或者在这个特定的方法中做一些半技巧性的事情,我对此持开放态度

您可以先将字符串流设置为静态变量:

{
  static std::stringstream ss;
  static bool ss_init = false;
  static std::string emtpy_string;
  if (!ss_init) { ss.imbue(std::locale("")); ss_init = true; }
  ss.str(empty_string);
  // ...
}

如果这仍然是一个瓶颈,你可以考虑一个替代的格式化库,比如fastformat。

1 using namespace std;
2 template <typename T>
3 string AddCommas(T data);
4 template <>
5 string AddCommas<int>(int data)
6 { 
7   stringstream ss; ss << data; string s = ss.str();
8   if (s.length() > 3)
9       for (int i = s.length()-3; i > 0; i -= 3)
10          s.insert(i,",");
11  return s;
12 }

您可以长时间使用相同的代码。替身有点棘手。

13 template <>
14 string AddCommas<double>(double data)
15 {
16  stringstream ss; ss << fixed << data; string s = ss.str();
17  string intPart, decPart = "";
18  int pos = s.find('.');
19  if (pos != string::npos) {
20      intPart = s.substr(0,pos);
21      decPart = s.substr(pos,pos-s.length());
22      //remove trailing zeros
23      for (int i = decPart.length()-1; i > 0; i--) {
24          if (decPart[i] == '0') decPart.erase(i);
25          else break;
26      }
27      // remove decimal point if no decimals
28      if (decPart.length() == 1) decPart = "";
29  }
30  else intPart = s;
31  //insert commas
32  if (intPart.length() > 3) {
33      for (int i = intPart.length()-3; i > 0; i -= 3) intPart.insert(i,",");
34  }
35  s = intPart + decPart;
36  return s;
37 }

你可以做一个浮子。如果要设置精度,则会出现唯一的问题。然后你只需要制作一个独立的函数,并添加一个参数来提高精度。此外,您还需要更改一些代码:

ss << fixed << setprecision(precision) << data; //...

以及拆下管路22至28。