【问题标题】:CLang-Tidy warning that rand() has limited randomnessCLang-Tidy 警告 rand() 具有有限的随机性
【发布时间】:2019-12-13 13:18:02
【问题描述】:
toZero = rand() % N;

这行代码给了我 Clang-Tidy:rand() 的随机性有限。为什么会出现这个警告?我该如何解决?

【问题讨论】:

标签: c random warnings clang-tidy


【解决方案1】:

尽管rand() 适用于很多应用程序(尤其是像 Park-Miller 和 Bays-Durham shuffle 这样的扩展),但一些代码检查工具将其等同于缩小版的魔鬼。

Clang-Tidy 警告您,它可能没有足够的随机属性来满足您的需求。

【讨论】:

  • 是否可以向我发送一个代码 sn-p,其中 Clang-Tidy 在使用 rand() 时不会警告我?
【解决方案2】:

是否可以向我发送一个代码 sn-p,其中 Clang-Tidy 在使用 rand() 时不会警告我?

如果您坚持使用rand(),则必须禁用警告:

toZero = rand() % N; // NOLINT(cert-msc30-c, cert-msc50-cpp)

更好的选择是改用<random> 库和函数。

一个例子:

#include <iostream>
#include <random>
#include <type_traits>

// A function to return a seeded random number generator.
inline std::mt19937& generator() {
    // the generator will only be seeded once (per thread) since it's static
    static thread_local std::mt19937 gen(std::random_device{}());
    return gen;
}

// A function to generate integers in the range [min, max]
template<typename T, std::enable_if_t<std::is_integral_v<T>>* = nullptr>
T my_rand(T min, T max) {
    std::uniform_int_distribution<T> dist(min, max);
    return dist(generator());
}

// A function to generate floats in the range [min, max)
template<typename T, std::enable_if_t<std::is_floating_point_v<T>>* = nullptr>
T my_rand(T min, T max) {
    std::uniform_real_distribution<T> dist(min, max);
    return dist(generator());
}

int main() {
    unsigned N = 100;
    std::cout << my_rand(0U, N - 1) << '\n'; // unsigned int:s instead of rand() % N
    std::cout << my_rand(-5., 5.) << '\n';   // double's
}

【讨论】:

    【解决方案3】:

    函数rand() 不是 C++ 函数,而是 C 函数。它来自 stdlib.h,并在 ISO/IEC 9899(C 编程语言)中定义。 它不保证可移植的高随机性水平。 有许多不同的实现可能,标准中没有适当的质量控制。 rand() 的典型实现是:

    static int next = (int) time();
    int rand(void) {
        next = next * 1103515245 + 12345;
        return((unsigned)(next/65536) % 32768);
    }
    

    也就是说,大多数时候,rand() 是一个 PRNG,根本不使用任何熵,可能除了 next 的初始值。

    所以你应该使用的是 C++11 随机库。以下是它的工作原理:

    #include <random>
    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(1, 6);
    auto dice = std::bind(distribution, generator);
    int roll = dice();
    

    演示:https://pastebin.run/pzhw6s36g9mf

    注意事项: uniform_int_distribution&lt;int&gt; 生成一个分布函数,该函数将从底层生成器中检索在给定范围之间均匀分布的数字。这很重要:模不是均匀分布函数。只是做类似int roll = 1 + nextInt() % 6 的事情并不是均匀分布的。 (感谢 Christian Hujer)

    【讨论】:

      猜你喜欢
      • 2018-04-10
      • 1970-01-01
      • 2017-01-24
      • 2021-10-23
      • 1970-01-01
      • 2021-09-04
      • 2019-03-26
      • 1970-01-01
      • 2018-12-15
      相关资源
      最近更新 更多