【问题标题】:C++ STL random number generation returning the same numberC ++ STL随机数生成返回相同的数字
【发布时间】:2016-06-15 20:07:54
【问题描述】:

我没有找到类似的问题,所以如果已经被问到,我很抱歉。无论如何,这是我的功能:

#ifndef OPTIMALIZATION_HPP
#define OPTIMALIZATION_HPP

#include<utility>
#include<random>
#include<experimental/random>
#include<functional>
#include<experimental/functional>
#include<experimental/tuple>
#include<algorithm>
#include<type_traits>
#include<iostream>

namespace numerics{
    template<
        std::size_t population_size, std::size_t generations,
        typename Func,
        typename Compare,
        typename Generator=std::default_random_engine,
        template<typename>
            typename RealDistribution=std::uniform_real_distribution,
        template<typename>
            typename IntegerDistribution=std::uniform_int_distribution,
        typename ...Ts
    >
    auto optimize(
            const Func& function, const Compare& comp,
            const std::pair<Ts,Ts>&... ranges
    ){

        constexpr std::size_t range_argument_count=sizeof...(ranges);
        static_assert(range_argument_count>2,
                "Function needs at least two range arguments"
        );

        //RANDOM NUMBER GENERATORS LAMPDA FUNCTIONS
        auto real_random_generator=[&](const std::pair<auto,auto> range){
            return std::bind(
                    RealDistribution<decltype(range.first)>(range.first,range.second),
                    Generator()
            );
        };

        auto integer_random_generator=[&](const std::pair<auto,auto>& range){
            return std::bind(
                    IntegerDistribution<decltype(range.first)>(range.first,range.second),
                    Generator()
            );
        };

        //MAKING TUPLE OF GENERATORS FOR SPECIFIC RANGES ARGUMENTS
        auto generator_objects=std::make_tuple(
                integer_random_generator,
                real_random_generator
        );
        auto generators=std::make_tuple(
                std::get<std::is_floating_point<decltype(ranges.first)>::value> //UPDATE FOR C++17
                (generator_objects)(ranges)...
        );
        //RANDOMIZES NUMBERS FINE!
        std::cout << std::get<0>(generators)() << std::endl;
        std::cout << std::get<0>(generators)() << std::endl;

        //SINGLE RANDOM INDIVIDUAL GENERATOR
        auto generate_random_individual=[&](const auto& gen){
            auto genotype=std::experimental::apply(
                    [&](auto... x){
                        return std::make_tuple(x()...);
                    },
                    gen
            );
            return std::make_pair(
                    std::experimental::apply(function,genotype),
                    genotype
            );
        };
        //RETURN THE SAME NUMBER!
        auto foo=generate_random_individual(generators);
        auto foo2=generate_random_individual(generators);
        auto foo3=generate_random_individual(generators);
        auto foo4=generate_random_individual(generators);
        std::cout << std::get<0>(foo.second) << std::endl;
        std::cout << std::get<0>(foo2.second) << std::endl;
        std::cout << std::get<0>(foo3.second) << std::endl;
        std::cout << std::get<0>(foo4.second) << std::endl;
        return 1.;
}}
#endif

最有趣的部分是我通过其中一个生成器的函数调用进行随机化,它工作正常(行://RANDOMIZES NUMBERS FINE!) 当我在函数 generate_random_individual 中执行此操作时(使用具有特定范围的少数生成器对象),通过对相同对象集的相同函数调用(因此我没有制作新生成器),它在最后一个 couts 中返回相同的数字。

如果有人需要,我可以提供测试用例,我不确定是否应该包括这些。

编辑:我将此作为示例,如果您想知道错误的确切位置,请参阅我的回答,谢谢您的帮助。

【问题讨论】:

  • TL;DR;只播种一次。
  • 我看不到你在哪里播种你的生成器(我可能错过了一些东西) - 如果你不播种,你总是会得到相同的序列。
  • @JesperJuhl 我必须播种吗?我正在使用随机库,我希望每次调用 generate_random_individual 时都有不同的输出。似乎这个lampda函数使用相同的生成器,因为它通过lampda调用获取那些,所以它应该返回不同的随机值(参见两个调用:std::cout (generators)()
  • 你需要创建最小的个例子。
  • 是的,您必须为它们播种,否则程序的每次调用都将具有相同的值。此外,您需要重用生成器并且不要重新创建它们,因为它会再次重置随机序列。

标签: c++ c++11 random stl c++14


【解决方案1】:

每次您想使用随机数时,您都在创建新的生成器。我不知道如何为这些生成器生成种子,但显然它为您创建的每个生成器实例使用相同的种子。相反,您应该做的是创建一个所有发行版都使用的生成器。

您可能想查看提升随机类提供的内容,并检查那里的一些示例。

【讨论】:

  • “你可能想看看提升随机类提供什么”没有比当前标准 IMO 更好的了。
  • 是的。不要重新生成生成器。重复使用它们(并正确播种 - 一次)。
  • 我真的重新生成生成器?如果你能帮我指出来,我在哪里这样做?
  • 在你调用构造函数 Generator() 的每个地方,你都在创建一个新的生成器。您应该将生成器作为参考传递,而不是调用构造函数。
  • @and 我只在创建 generators 变量时使用 Generator() 。之后我在lampda函数generate_random_individual中使用每个带有重载()的生成器......
【解决方案2】:

问题已解决 - 我在传入我的一个函数时忘记添加 & ,即此处:

auto genotype=std::experimental::apply(
                    [&](auto&... x){ //THIS LINE!
                        return std::make_tuple(x()...);
                    },
                    gen
            );

因此,正如你们大多数人所说,它正在复制生成器,感谢您的输入。

【讨论】:

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