调用随机数生成成员函数不会产生完全随机数 [英] Calling a random number generating member function doesn't produce entirely random numbers

查看:57
本文介绍了调用随机数生成成员函数不会产生完全随机数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用C ++创建一个wxWidget应用程序,其中在程序开始时,我希望应用程序窗口包含具有随机颜色的像素,如下所示:

I'm creating a wxWidget application with C++ where at the start of the program I want the application window to contain pixels with random colors like this:

在上面的应用程序中,有3600个像素(60 x 60),我通过使用uniform_int_distribution

In the above application there are 3600 pixels (60 x 60) and I have given each pixel a random RGB color by using uniform_int_distribution

以上图像中像素的颜色是使用我的代码中的以下函数生成的:

The colours for the pixels in the image above are generated at the moment using the following function in my code:

void random_colors(int ctable[][3], int n)
{
  // construct a trivial random generator engine from a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine generator (seed);
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<n; i++)
  {
      for(int j=0; j<3; j++)
      {
        ctable[i][j] = distribution(generator);
      }
  }
}

我通过给此函数一个尺寸为3600 x 3的表来完成此操作,此函数将填充颜色的值.

I do this by giving this function a table with dimensions 3600 x 3 and this function will fill in the values for the colours.

但是,这不是我想要的.我想要创建一个名为somNode的类,其中每个somNode -object代表图片中的一个像素(RGB值作为成员数组属性).在此somNode类中,我有一个成员函数,该成员函数使用uniform_int_distribution在构造每个somNode时赋予其自己的随机RGB颜色.这是为每个somNode创建随机颜色的函数:

This way however is not what I want. What I want is to create a class called somNode where each somNode-object represents a pixel in the picture (with RGB values as a member array attribute). In this somNode-class I have a member function using uniform_int_distribution to give when constructed each somNode its own random RGB colour. This is the function which creates the random colour for each somNode:

void rand_node_colour(int nodeWeights[])
{
  // construct a trivial random generator engine from a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine generator (seed);
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<3; i++)
  {
    nodeWeights[i] = distribution(generator);
  }
}

nodeWeights成员数组表示somNode的RGB值.现在,当我创建上图中的"som-grid"(对应于3600 somNode的3600像素)时,我使用以下代码(看一下som构造函数):

the nodeWeights member array represents the RGB-value of the somNode. Now when I create this "som-grid" what I have in the image above (the 3600 pixels corresponding to 3600 somNodes) I use the following code (take a look at the som-constructor):

#include "somNode.h"
#include <vector>

class som
{
    public:
        double learning_rate;
        std::vector<somNode> somGrid;
    public:
        som(double lrate);
        void epoch();
        void trainOnce();

};

/*
* Initialize the som grid
*/
som::som(double lrate)
{
    learning_rate = lrate;
    // Create the som grid
    for(int i=0; i<60; i++)
    {
        for(int j=0; j<60; j++)
        {
            int xL = j*10;
            int xR = (j+1)*10;
            int yT = i*10;
            int yB = (i+1)*10;
            somGrid.push_back(somNode(xL, xR, yB, yT));
        }
    }
}

// Train som by one epoch
void som::epoch()
{

}

// Train som by one color
void som::trainOnce()
{

}

因此,我有一个vector<somNode> somGrid,在构造它们时将所有这3600个somNode推入其中.构造每个节点时,将调用somNode成员函数rand_node_colour,该函数创建RGB值.

So I have a vector<somNode> somGrid where I push all these 3600 somNodes when I construct them. When each node is constructed the somNode member function rand_node_colour is called which creates the RGB-value.

但是,当我实现此代码而不是最初使用的代码时,会得到以下结果:

When however I implement this code instead of the one I used at first I get this result:

您可以看到有一个清晰的图案,所以这里出了点问题.我的问题是:创建somNodes时,随机数生成中发生了什么?为什么它不会产生与我上面使用的代码相同的结果?

You can see that there is a clear pattern so something is going wrong here. My question is: What is happening in the random number generation when somNodes are created? Why it doesn't produce the same result as the code I used above?

P.S.这是somNode.cpp:

#include <random>
#include <iostream>
#include <chrono>
#include<cmath>

void rand_node_colour(int nodeWeights[]);

/*
* This class represent a node in the som-grid
*/
class somNode
{
    public:
        // Weight of the node representing the color
        int nodeWeights[3];
        // Position in the grid
        double X, Y;
        // corner coorinates for drawing the node on the grid
        int x_Left, x_Right, y_Bottom, y_Top;

    public:
        // Constructor
        somNode(int xL, int xR, int yB, int yT);
        void editWeights(int r, int g, int b);
        double getDistance(int r, int g, int b);
};


somNode::somNode(int xL, int xR, int yB, int yT)
{
    // Set the corner points
    x_Left = xL;
    x_Right = xR;
    y_Bottom = yB;
    y_Top = yT;
    // Initialize random weights for node
    rand_node_colour(nodeWeights);
    // Calculate the node's position (center coordinate)
    X = x_Left + (double)((x_Right - x_Left)/double(2));
    Y = y_Bottom + (double)((y_Top - y_Bottom)/double(2));
}

void somNode::editWeights(int r, int g, int b)
{
    nodeWeights[0] = r;
    nodeWeights[1] = g;
    nodeWeights[2] = b;
}

double somNode::getDistance(int r, int g, int b)
{
    return sqrt(pow(nodeWeights[0]-r, 2) + pow(nodeWeights[1]-g, 2) + pow(nodeWeights[2]-b, 2));
}


void rand_node_colour(int nodeWeights[])
{
  // construct a trivial random generator engine from a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine generator (seed);
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<3; i++)
  {
    nodeWeights[i] = distribution(generator);
  }
}

推荐答案

此处的问题是您不断在rand_node_colour中重新创建随机数生成器并将其植入种子.您将其称为紧密循环,这样您可以获得相同的时间,这意味着种子将是相同的,并且这意味着生成的随机数将是相同的.

The issue here is that you constantly recreate and seed the random number generator in rand_node_colour. You call it in a tight loop so you can get the same time which means the seed will be the same and that means the random numbers generated will be the same.

您需要做的是将生成器播种一次,然后继续使用其随机输出.修复代码的一种简单方法是在函数中将其设置为static,以便仅对其初始化一次,并且每次对该函数的后续调用都将继续进行,而不是重新启动生成器.如果我们这样做,代码就会变成

What you need to do is seed the generator once and then keep using its random output. An easy way to fix you code would be to make it static in the function sos it is only initialized once and each subsequent call to the function will continue on instead of start the generator all over. If we do that the code becomes

void rand_node_colour(int nodeWeights[])
{
  // construct a trivial random generator engine from a time-based seed:
  static std::default_random_engine generator (std::chrono::system_clock::now().time_since_epoch().count());
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<3; i++)
  {
    nodeWeights[i] = distribution(generator);
  }
}

这篇关于调用随机数生成成员函数不会产生完全随机数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆