uniform_int_distribution used wrong here? (my resu

2019-08-10 02:47发布

Version 3 Moved generator into a class. Is my new random number generation technique correct this time?

template<typename T = int>
    class MyRandomGenerator
    {
    public:
        MyRandomGenerator()
        {
            std::random_device rd;
            gen = std::mt19937{rd()};
        }

        T getNumber(const T& From, const T& To)
        {
            std::uniform_int_distribution<T> dist(From, To);
            return dist(gen);
        }
    private:
        std::mt19937 gen;
    };

And here my new position calculators:

auto calculate_x_position = [&]() ->sf::Uint32 {return RandGen.getNumber(0, W - 1); };
auto calculate_y_position = [&]() ->sf::Uint32 {return RandGen.getNumber(0, H - 1); };

Same pattern/problem as before: enter image description here

Version 2 Creating ~3 maps per second of 10.000 stars per map. The outcome is still the same. Moreover, it gets even more clear that there is a pivot to the top of the maps. Example: enter image description here

Original Question: i went into trying to draw a simple star map. For this i first calculate the x and y position for the stars. X and Y are within the range of width and height of the window.

This is my random number generating function:

    template<typename T>
    T getRandomNumberBetween(const T& Min, const T& Max)
    {
        static std::random_device rd;
        static std::uniform_int_distribution<T> dist{Min, Max};
        return dist(rd);
    }

And i use it like this:

auto calculate_x_position = std::bind(inc::getRandomNumberBetween<sf::Uint32>, 0, Width-1);
    auto calculate_y_position = std::bind(inc::getRandomNumberBetween<sf::Uint32>, 0, Height-1);
x = calculate_x_position(); //...

But as i draw my map over and over again it seems to me that there is a pivot to where most stars tend to be. E.g. the majority of stars are in the upper half of my window.

Example:

enter image description here

Am i using it wrong or having a wrong expectation here?... Because here it says:

This distribution produces random integers in a range [a,b] where each possible value has an equal likelihood of being produced.

Kind Regards

2条回答
2楼-- · 2019-08-10 03:12

Uniform distribution does not specifically mean that you will get an equal amount in each quadrant of the screen; It means that there is an equal chance of each point appearing. So if you do a simple 50:50 trial, it does not mean you will get 50:50 results.

However if you did a test with say 1,000,000 stars it is very likely that they will be nearly uniformly distributed. To me this seems like an error in sample size

查看更多
对你真心纯属浪费
3楼-- · 2019-08-10 03:26

There are a couple of ways you could improve your code. An engine is only meant to be created once, not everytime you want a random number. And you usually don't want to use std::default_random_engine because it may default to std::rand. A better default is std::mt19937. My example is pulled from The bell has tolled for rand():

#include <random>

std::mt19937& prng_engine()
{
  thread_local static std::random_device rd{};
  thread_local static std::mt19937 engine{rd()};

  // Or you can replace the two previous lines with:
  //thread_local static std::mt19937
  //  prng{std::random_device{}()};

  return engine;
}

template<typename T>
T getRandomNumberBetween(T Min, T Max)
{
    thread_local static std::uniform_int_distribution<T> dist{Min, Max};
    return dist(prng_engine());
}
查看更多
登录 后发表回答