1. rand函数(在<cstdlib>头文件中)
    • 基本用法
      • rand函数用于生成伪随机整数。它会返回一个介于0和RAND_MAX(一个在<cstdlib>中定义的常量,其值至少为32767)之间的整数。例如:
      #include <iostream>
      #include <cstdlib>
      int main() {
          int randomNumber = rand();
          std::cout << "随机数: " << randomNumber << std::endl;
          return 0;
      }
      
      • 每次运行这个程序,都会得到一个不同的随机整数。不过,这个随机数序列是固定的,因为rand函数是基于一个初始的“种子”(seed)来生成序列的。
    • 设置种子
      • 为了得到更随机的序列,可以使用srand函数来设置种子。通常会使用当前时间作为种子,因为时间是不断变化的。需要包含<ctime>头文件来获取当前时间。例如:
      #include <iostream>
      #include <cstdlib>
      #include <ctime>
      int main() {
          srand(static_cast<unsigned int>(time(nullptr)));
          int randomNumber = rand();
          std::cout << "随机数: " << randomNumber << std::endl;
          return 0;
      }
      
      • 在这里,time(nullptr)返回从1970年1月1日00:00:00 UTC到当前时间的秒数,将其转换为unsigned int类型后作为种子传递给srand函数。这样每次运行程序时,由于时间不同,种子不同,rand函数生成的随机数序列也会不同。
    • 生成指定范围内的随机数
      • 如果要生成一个在[min, max]范围内的随机数,可以使用以下公式:int randomInRange = rand() % (max - min + 1)+ min;。例如,要生成一个介于1和10之间的随机数:
      #include <iostream>
      #include <cstdlib>
      #include <ctime>
      int main() {
          srand(static_cast<unsigned int>(time(nullptr)));
          int min = 1;
          int max = 10;
          int randomInRange = rand() % (max - min + 1)+ min;
          std::cout << "在[1, 10]范围内的随机数: " << randomInRange << std::endl;
          return 0;
      }
      
  2. randomuniform_int_distribution(在<random>头文件中,C++ 11引入)
    • 基本用法
      • 这种方式提供了更灵活和更高质量的随机数生成方式。首先,需要创建一个随机数引擎和一个分布对象。例如,使用std::mt19937(梅森旋转算法随机数引擎)和std::uniform_int_distribution来生成均匀分布的整数随机数。
      #include <iostream>
      #include <random>
      int main() {
          std::mt19937 rng(std::random_device{}());
          std::uniform_int_distribution<int> dist(1, 10);
          int randomNumber = dist(rng);
          std::cout << "随机数: " << randomNumber << std::endl;
          return 0;
      }
      
      • 在这里,std::random_device用于获取一个真正随机的种子(如果有硬件支持的话),将其作为参数传递给std::mt19937随机数引擎rng。然后创建了一个std::uniform_int_distribution对象dist,指定生成的随机数范围是110。最后通过dist(rng)生成一个在这个范围内的随机数。
    • 生成不同类型的随机数分布
      • 除了均匀分布的整数随机数,还可以生成其他分布的随机数。例如,使用std::normal_distribution来生成正态分布的随机数。
      #include <iostream>
      #include <random>
      int main() {
          std::mt19937 rng(std::random_device{}());
          std::normal_distribution<double> dist(0.0, 1.0);
          double randomNumber = dist(rng);
          std::cout << "正态分布随机数: " << randomNumber << std::endl;
          return 0;
      }
      
      • 这里std::normal_distribution对象dist的参数0.01.0分别表示正态分布的均值和标准差,通过dist(rng)生成一个符合该正态分布的双精度浮点数随机数。

2 条评论

  • @ 2024-12-28 18:47:52
    1. 线性同余法(自定义简单的伪随机数生成器)

      • 原理
        • 线性同余法是一种简单的伪随机数生成算法。它基于以下递推公式:X_{n + 1}=(a * X_{n}+c) \bmod m,其中X_{n}是当前的随机数,X_{n + 1}是下一个随机数,acm是常数。通过合适地选择这些常数,可以生成看起来比较随机的序列。
      • 示例代码
        #include <iostream>
        class RandomGenerator {
        private:
            long long seed;
            long long a;
            long long c;
            long long m;
        public:
            RandomGenerator(long long initial_seed, long long multiplier, long long increment, long long modulus)
                : seed(initial_seed), a(multiplier), c(increment), m(modulus) {}
            int generate() {
                seed = (a * seed + c) % m;
                return static_cast<int>(seed);
            }
        };
        int main() {
            RandomGenerator rg(1, 1103515245, 12345, 2147483648);
            int min = 1;
            int max = 10;
            int range_size = max - min + 1;
            int randomNumber = rg.generate() % range_size + min;
            std::cout << "生成的在[" << min << ", " << max << "]范围内的随机数是: " << randomNumber << std::endl;
            return 0;
        }
        
      • 解释
        • 首先定义了一个RandomGenerator类,它有四个私有成员变量:seed(种子)、a(乘法因子)、c(增量)和m(模数)。构造函数接受初始种子、乘法因子、增量和模数作为参数来初始化这些成员变量。
        • generate函数根据线性同余法的公式更新种子,并将生成的新种子转换为int类型返回。
        • main函数中,创建了一个RandomGenerator对象rg,并传入了合适的参数(这些参数可以根据需要调整)。然后定义了范围minmax,计算出范围大小range_size。通过rg.generate() % range_size + min将生成的随机数映射到[min, max]范围内并输出。
    2. 利用位运算(一种不太常见但有趣的方式)

      • 原理
        • 可以通过对一些基本的随机数源(如系统时间的某些位)进行位运算来增加随机性,然后再将其转换到指定的范围。这种方法通常需要结合其他技术,因为单独的位运算可能无法提供足够好的随机性。
      • 示例代码
        #include <iostream>
        #include <ctime>
        int main() {
            unsigned int time_seed = static_cast<unsigned int>(time(nullptr));
            // 对时间种子进行位运算来获取更随机的种子
            unsigned int seed = (time_seed << 13) ^ (time_seed >> 9);
            int min = 1;
            int max = 10;
            int range_size = max - min + 1;
            int randomNumber = ((seed & 0xFFFF) % range_size)+ min;
            std::cout << "生成的在[" << min << ", " << max << "]范围内的随机数是: " << randomNumber << std::endl;
            return 0;
        }
        
      • 解释
        • 首先包含了<iostream><ctime>头文件。通过time(nullptr)获取当前时间作为种子的基础,将其存储在time_seed中。
        • time_seed进行位运算:(time_seed << 13) ^ (time_seed >> 9),这样可以改变种子的二进制表示,增加一些随机性,结果存储在seed中。
        • 定义了范围minmax,计算出范围大小range_size。通过((seed & 0xFFFF) % range_size)+ min,先使用seed & 0xFFFF获取seed的低16位,再将其对range_size取余并加上min,将结果映射到[min, max]范围内并输出。不过这种方法生成的随机数质量可能不如使用标准库中的随机数生成器高。
    3. 结合哈希函数(如果需要更复杂的随机数生成)

      • 原理
        • 哈希函数可以将输入数据(如时间戳、用户输入等)转换为看起来更随机的输出。可以利用哈希函数的这个特性来生成随机数。例如,使用std::hash(C++ 11引入)来对一些数据进行哈希处理,然后将哈希值转换为指定范围内的随机数。
      • 示例代码
        #include <iostream>
        #include <unordered_set>
        #include <ctime>
        int main() {
            std::unordered_set<int> generated_numbers;
            std::size_t hash_seed = static_cast<std::size_t>(time(nullptr));
            int min = 1;
            int max = 10;
            int range_size = max - min + 1;
            while (true) {
                std::size_t hash_value = std::hash<std::size_t>()(hash_seed);
                int randomNumber = static_cast<int>(hash_value % range_size)+ min;
                if (generated_numbers.find(randomNumber) == generated_numbers.end()) {
                    generated_numbers.insert(randomNumber);
                    std::cout << "生成的在[" << min << ", " << max << "]范围内的随机数是: " << randomNumber << std::endl;
                    break;
                }
                hash_seed++;
            }
            return 0;
        }
        
      • 解释
        • 包含了<iostream><unordered_set><ctime>头文件。std::unordered_set用于存储已经生成的随机数,以避免重复。
        • 通过time(nullptr)获取当前时间作为哈希种子hash_seed的基础。
        • 在循环中,使用std::hash<std::size_t>()(hash_seed)hash_seed进行哈希处理,得到hash_value。然后将hash_valuerange_size取余并加上min,将结果转换为int类型,得到randomNumber
        • 检查randomNumber是否已经在generated_numbers集合中。如果不在,将其插入集合,输出这个随机数并退出循环;如果在,就增加hash_seed并再次尝试,直到生成一个未出现过的随机数。这种方法可以生成相对更随机的数,并且可以避免简单随机数生成方法可能出现的重复问题。
    • @ 2024-12-28 18:47:00
      1. 使用rand函数(传统方式,C++早期版本常用)
        • 原理和基本公式
          • rand函数会返回一个介于0和RAND_MAX(在<cstdlib>头文件中定义,其值至少为32767)之间的伪随机整数。要生成指定范围[min, max]minmax为整数,且min <= max)内的随机数,可以使用公式int randomNumber = rand() % (max - min + 1)+ min;
        • 示例代码
          #include <iostream>
          #include <cstdlib>
          #include <ctime>
          int main() {
              // 设置随机数种子,以获取不同的随机数序列
              srand(static_cast<unsigned int>(time(nullptr)));
              int min = 1;
              int max = 10;
              int randomNumber = rand() % (max - min + 1)+ min;
              std::cout << "生成的在[" << min << ", " << max << "]范围内的随机数是: " << randomNumber << std::endl;
              return 0;
          }
          
        • 解释
          • 首先包含了<iostream>用于输出,<cstdlib>用于randsrand函数,<ctime>用于获取时间来设置随机数种子。
          • main函数中,通过srand(static_cast<unsigned int>(time(nullptr)))设置随机数种子。time(nullptr)返回从1970年1月1日00:00:00 UTC到当前时间的秒数,将其转换为unsigned int类型后作为种子传递给srand函数,这样每次运行程序可以得到不同的随机数序列。
          • 然后定义了范围的下限min为1和上限max为10。根据公式rand() % (max - min + 1)+ minrand() % (max - min + 1)计算出一个介于0和max - min之间的数,再加上min,就得到了一个介于minmax之间的随机数,最后将这个随机数输出。
      2. 使用<random>头文件(C++ 11及以后版本推荐)
        • uniform_int_distribution类(用于生成均匀分布的整数随机数)
          • 基本原理和使用步骤
            • 首先需要创建一个随机数引擎,例如std::mt19937(梅森旋转算法随机数引擎),它是一个伪随机数生成器。然后创建一个uniform_int_distribution对象来指定随机数的范围,最后通过这个分布对象和随机数引擎来生成指定范围内的随机数。
          • 示例代码
            #include <iostream>
            #include <random>
            int main() {
                std::mt19937 rng(std::random_device{}());
                int min = 1;
                int max = 10;
                std::uniform_int_distribution<int> dist(min, max);
                int randomNumber = dist(rng);
                std::cout << "生成的在[" << min << ", " << max << "]范围内的随机数是: " << randomNumber << std::endl;
                return 0;
            }
            
          • 解释
            • 包含<iostream><random>头文件。<random>头文件提供了更高级的随机数生成功能。
            • main函数中,std::mt19937 rng(std::random_device{}());创建了一个mt19937随机数引擎rngstd::random_device用于获取一个真正随机的种子(如果有硬件支持的话),将其作为参数传递给mt19937
            • 接着定义了范围min为1和max为10,std::uniform_int_distribution<int> dist(min, max);创建了一个uniform_int_distribution对象dist,它指定了生成的随机数范围是从minmax
            • 最后通过int randomNumber = dist(rng);,使用distrng生成一个在指定范围内的随机数,并将其输出。
        • uniform_real_distribution类(用于生成均匀分布的实数随机数)
          • 基本原理和使用步骤
            • 与生成整数随机数类似,需要先创建随机数引擎,然后创建uniform_real_distribution对象来指定实数范围,最后生成随机数。不过这里生成的是浮点数。
          • 示例代码
            #include <iostream>
            #include <random>
            int main() {
                std::mt19937 rng(std::random_device{}());
                double min = 1.0;
                double max = 10.0;
                std::uniform_real_distribution<double> dist(min, max);
                double randomNumber = dist(rng);
                std::cout << "生成的在[" << min << ", " << max << "]范围内的随机数是: " << randomNumber << std::endl;
                return 0;
            }
            
          • 解释
            • 同样先创建了mt19937随机数引擎rng
            • 定义了浮点数范围的下限min1.0和上限max10.0,然后创建std::uniform_real_distribution<double> dist(min, max);对象dist来指定生成的浮点数随机数范围。
            • 通过double randomNumber = dist(rng);生成一个在指定范围内的浮点数随机数,并输出。
      • 1