【问题标题】:function returns all the same random number [duplicate]函数返回所有相同的随机数[重复]
【发布时间】:2014-08-09 03:45:03
【问题描述】:

我在 c++ 中有一个函数,它返回两个数字之间的随机浮点数。代码如下:

float randFloatNumBetween(float lower, float upper) {
    srand((unsigned)time(NULL));
    return lower + ((float) rand() / RAND_MAX) * (upper - lower); 
}

当我使用参数下限为 0.0 上限为 10.0 的参数调用此函数时,它会返回如下数字:

1.00503555
1.01846383
1.03463534
1.05263234
1.06461514

如何让我的函数在逗号前后返回不同的数字?像这样的数字:

5.00503555
3.01846383
1.03463534
4.05263234
8.06461514

【问题讨论】:

    标签: c++ random


    【解决方案1】:

    显然,您每次调用srand 时都需要更改种子值。根据您留下的 cmets,这似乎不是您的问题,但需要指出。

    一些随机数生成器(我知道微软的rand 就是其中之一)在初始种子和生成的第一个数字之间存在相关性。由于时间变化不是很快,因此您从播种中获得的数字也往往是相关的。

    解决此问题的最佳方法是使用更好的随机数生成器,例如 <random> 标头中的 C++11 生成器:http://en.cppreference.com/w/cpp/numeric/random 或它们在 boost 库中的前身。

    否则,请确保在播种后生成几个一次性随机数。

    【讨论】:

      【解决方案2】:

      您在每次迭代中调用srand,但调用srand should be called only once。将srand((unsigned)time(NULL)); 放置在此函数之外的文件范围内。

      【讨论】:

      • 但是现在我不明白了,为什么每次我调用程序时仍然返回当前时间相同的数字?当我运行第二次程序时,它不应该也改变前2位吗?
      • 没有。它不会。阅读提供的链接中接受的答案。
      【解决方案3】:

      如果您的编译器支持 C++11 功能,您可以执行以下操作:

      #include <chrono>
      #include <random>
      #include <iostream>
      #include <type_traits>
      
      template<typename T>
      typename std::enable_if<std::is_floating_point<T>::value, T>::type randNumBetween(T lower, T upper, std::default_random_engine &gnr) {
        if(lower > upper) std::swap(lower, upper);
        std::uniform_real_distribution<T> distribution(lower, upper);
        return distribution(gnr);
      }
      
      template<typename T>
      typename std::enable_if<std::is_integral<T>::value, T>::type randNumBetween(T lower, T upper, std::default_random_engine &gnr) {
        if(lower > upper) std::swap(lower, upper);
        std::uniform_int_distribution<T> distribution(lower, upper);
        return distribution(gnr);
      }
      
      int main() {
        auto seed = std::chrono::system_clock::now().time_since_epoch().count();
        std::default_random_engine gnr(seed);
        for(auto i(0); i < 10; ++i) std::cout << randNumBetween(10, 20, gnr) << std::endl;
        for(auto i(0); i < 10; ++i) std::cout << randNumBetween(10.0, 20.0, gnr) << std::endl;
        return 0;
      }
      

      DEMO

      在这个漂亮的video lecture Stephan T. Lavavej 中解释了为什么使用rand() 被认为是有害和不安全的。

      【讨论】:

        猜你喜欢
        • 2013-01-31
        • 2011-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多