简体   繁体   English

在 C++ 中生成随机字符串的最有效方法是什么?

[英]What is the most efficient way to generate random strings in C++?

I need to generate random strings efficiently.我需要有效地生成随机字符串。 In the following, you will see my first try.在下文中,您将看到我的第一次尝试。 I compiled the code with gcc and -O3 optimization level.我用 gcc 和 -O3 优化级别编译了代码。 It takes 18.5 seconds to generate 10^7 random strings of length 64:生成 10^7 个长度为 64 的随机字符串需要18.5 秒

#include <iostream>
#include <random>
#include <algorithm>

std::string chars {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()`~-_=+[{]{|;:'\",<.>/?"};
std::random_device rd;
std::mt19937 generator(rd());
  
std::string rand_str (int length) {
  std::string output (chars);
  std::shuffle(output.begin(), output.end(), generator);
  return output.substr(0, length);
}

int main() {
  std::string str;
  for (long i=0; i<10000000; ++i)
      str = rand_str (64);
}

I checked std::sample in c++17 and it is not faster than the above method.我检查了 c++17 中的std::sample ,它并不比上述方法快。 In addition, it will not change the order of characters and so it is not really random.此外,它不会改变字符的顺序,因此它不是真正随机的。

Edit: The std::shuffle is not a good choice, since, it will not allow duplicates.编辑: std::shuffle不是一个好的选择,因为它不允许重复。 Based on comments I modified the code.根据评论,我修改了代码。 This time it takes more than 9 minutes for 10^7 random numbers.这次 10^7 个随机数需要9 多分钟

std::string rand_str (size_t length) {
  const size_t char_size = chars.size();
  std::uniform_int_distribution<> random_int (0, char_size - 1);
  std::string output;
  for (size_t i=0; i<length; ++i)
    output.push_back(chars[random_int(generator)]);
  return output;
}

Question问题

  • Are there more efficient ways to do this in modern C++?在现代 C++ 中是否有更有效的方法来做到这一点?

I appreciate any suggestions to improve the code.我感谢任何改进代码的建议。

#include <iostream>
#include <random>
#include <algorithm>
#include <chrono>

std::string chars {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()`~-_=+[{]{|;:'\",<.>/?"};
std::random_device rd;
std::mt19937 generator(rd());
  
std::string rand_str(int length) {
  std::string output;
  output.reserve(length);

  while(length>0)
  {
      auto randNumb = generator();
      while(randNumb > 93 && length--)
      {
        output.push_back(chars[randNumb%93]);
        randNumb/=93;
      }
  }
  return output;
}

int main() {
  auto startTP = std::chrono::system_clock::now();
  std::string rand_bytes;
  for (long i=0; i<10000000; ++i)
      rand_bytes = std::move(rand_str(64));
  auto endTP = std::chrono::system_clock::now();

  std::cout << "This took: " << std::chrono::duration_cast<std::chrono::microseconds>(endTP-startTP).count() << std::endl;
}

This takes around 3 seconds on my machine.这在我的机器上大约需要 3 秒。 The trick is to call the random number generator as little as possible and to allocate the memory only once.诀窍是尽可能少地调用随机数生成器,并且只分配一次 memory。

What I'm doing is converting randNumber from base 10 to base 93(the length of chars).我正在做的是将 randNumber 从基数 10 转换为基数 93(字符的长度)。 After that im using every base 93 digit as a different random number.之后,我使用每个基数 93 位作为不同的随机数。 This provides around 5 numbers per generated random number.这为每个生成的随机数提供了大约 5 个数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM