简体   繁体   English

有效地生成随机数

[英]Generating random numbers effectively

How do you generate random numbers effectively? 你如何有效地生成随机数?
Every time a random number program boots up, it starts spitting same numbers as before. 每次随机数程序启动时,它都会像以前一样开始吐出相同的数字。 (I guess because of quasi nature of random number generation) (我猜是因为随机数生成的准性质)
Is there a way, that random# generation becomes non-deterministic? 有没有办法,随机#生成变得不确定? sort of Entropy addition to generation that number generated after boot is in different sequence than last one. 除了生成之外,引入后生成的数字与最后一个序列的顺序不同。 (random random rather that quasi-random) (随机随机而非准随机)
Also, say range of such generation is (m,n) such that nm = x, is there a chance that a number say 'p' appears next time after x-1 other numbers have been generated. 此外,例如,这种生成的范围是(m,n)使得nm = x,在生成x-1个其他数之后,有可能下次出现数字'p'。 But next lot of such x numbers would not be same as sequence from last one. 但是接下来很多这样的x数字与最后一个数字的序列不一样。 Example: 例:
range: 1,5. 范围:1,5。 Generation : 2,4,5,1,3 (1st) 4,2,3,1,5 (2nd)... same numbers. 代:2,4,5,1,3(第一)4,2,3,1,5(第二)......相同的数字。
I out of nonplussed state of mind wrote this : 我出于困惑的心态写下了这个:

int num1 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1;
int num2 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1;

here range was (1,440). 这里的范围是(1,440)。 but it still generates numbers out of bound and zero, and it's frequency is not that great either. 但是它仍然会产生超出界限和零的数字,而且它的频率也不是那么好。 It is C#.NET code. 它是C#.NET代码。 Why so? 为什么这样?
your answers can be language agnostic / algorithmic / analytical. 您的答案可以是语言不可知/算法/分析。 Thanks in advance. 提前致谢。

Very few "random" number generators are actually random. 很少“随机”数字生成器实际上是随机的。 Almost all are pseudorandom, following a predictable sequence when started with the same seed value . 当使用相同的种子值启动时,几乎所有都是伪随机的,遵循可预测的序列。 Many pseudorandom number generators (PRNGs) get their seed from the date and time of their initial invocation. 许多伪随机数生成器 (PRNG)从其初始调用的日期和时间获取其种子。 Others get their seed from a source of random data supplied by the operating system, which often is generated from outside sources ( eg , mouse motion, keyboard activity). 其他人从操作系统提供的随机数据源获取其种子,这些数据通常是从外部源生成的( 例如 ,鼠标移动,键盘活动)。

The right way to seed a good random number generator is to not seed it. 种子好的随机数生成器的正确方法是不播种它。 Every good generator has a default mechanism to supply the seed, and it is usually much better than any you can come up with. 每个好的发电机都有一个默认的机制来供应种子,它通常比你想出的任何产品好得多。 The only real reason to seed the generator is if you actually want the same sequence of random numbers ( eg , when you're trying to repeat a process that requires randomness). 种子生成器的唯一真正原因是如果你真的想要相同的随机数序列( 例如 ,当你试图重复一个需要随机性的过程时)。

See http://msdn.microsoft.com/en-us/library/system.random.aspx for the details of the C# Random class, but basically, it uses a very well known and respected algorithm and seeds it with the date and time. 有关C#Random类的详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.random.aspx ,但基本上,它使用了一个众所周知且受人尊敬的算法,并将其与日期和时间。

To answer your key question, just use rand.Next(min, max+1) and you'll always get a random sequence of numbers between min and max inclusive. 要回答您的关键问题,只需使用rand.Next(min, max+1) ,您将始终获得minmax之间的随机数字序列。 The sequence will be the same every time you use the same seed. 每次使用相同的种子时,序列都是相同的。 But rand = new Random() will use the current time, and as long as your program is invoked with some separation in time, they'll be different. rand = new Random()将使用当前时间,并且只要您的程序在时间上分开调用,它们就会有所不同。

"Seed" the random number generator by getting the number of seconds since midnight and then passing it in: 通过获取自午夜以来的秒数然后将其传递到“种子”随机数生成器:

Random rand = new Random(secs);

This still does not generate perfectly random numbers, but should serve your purpose. 这仍然不会产生完全随机的数字,但应该符合您的目的。

Producing the same sequence over and over is often a feature, not a bug, as long as you control it. 反复生成相同的序列通常是一个功能,而不是一个bug,只要你控制它。 Producing a repeatable sequence makes debugging easier. 生成可重复的序列使调试更容易。 If you are serious about wanting a non-reproducible random sequence, you could look for a secure random number generator with this as a design aim. 如果你真的想要一个不可重现的随机序列,你可以寻找一个安全的随机数发生器,将其作为设计目标。 You've tagged your question C#, but since Java has http://docs.oracle.com/javase/1.4.2/docs/api/java/security/SecureRandom.html and the windows API has http://en.wikipedia.org/wiki/CryptGenRandom you may able to find an equivalent in C#. 你已经标记了你的问题C#,但是因为Java有http://docs.oracle.com/javase/1.4.2/docs/api/java/security/SecureRandom.html而且windows API有http:// en。 wikipedia.org/wiki/CryptGenRandom你可以在C#中找到一个等价物。

You can use a chaotic map to generate random numbers. 您可以使用混沌映射生成随机数。 The C++ code below (GenRandRea) returns a vector of random number using the so-called "Tent map" ( https://www.wikiwand.com/en/Tent_map ). 下面的C ++代码(GenRandRea)使用所谓的“Tent map”( https://www.wikiwand.com/en/Tent_map )返回随机数的向量。 The seed is an integer that is used to generate x (as a number between 0. and 1.) as input of the iterative map. 种子是一个整数,用于生成x(作为0和1之间的数字)作为迭代映射的输入。 Diferent seeds will generate different sequences. 不同的种子将产生不同的序列。

vector<double> GenRandRea(unsigned seed, int VecDim){
double x, y, f;
vector<double> retval;

x = 0.5*(abs(sin((double)seed)) + abs(cos((double)seed)));

for (int i = 0; i<(tentmap_delay + VecDim); i++) {
    if ((x >= 0.) && (x <= 0.5)) {
        f = 2 * tentmap_r * x;
    }
    else {
        f = 2 * tentmap_r * (1. - x);
    }

    if (i>=tentmap_delay) {
        y = (x*tentmap_const) - (int)(x*tentmap_const);
        retval.push_back(y);
    }
    x = f;
}
return retval;

} }

with

const double tentmap_r = 0.75; //parameter for the tent map
const int tentmap_delay = 50; /*number of interactions in the tent map 
                              allowing for sorting */
const double tentmap_const = 1.e6; //constant for the tent map

VecDim is the output vector dimension. VecDim是输出向量维度。 The ideia is to iterate at least (tentmap_delay + VecDim) turns and write the result in retval (a vector of doubles). ideia至少迭代(tentmap_delay + VecDim)并将结果写入retval(双精度矢量)。

To use this code: 要使用此代码:

vector<double> val;

val = GenRandRea(2, 10);
for (int kk=0; kk<10;kk++){
    cout << setprecision(9) << val[kk] << endl;
}

which will for example produce: 这将产生:

0.767902586 0.848146121 0.727780818 0.408328773 0.88750684 0.83126026 0.253109609 0.620335586 0.569496621 0.145755069 0.767902586 0.848146121 0.727780818 0.408328773 0.88750684 0.83126026 0.253109609 0.620335586 0.569496621 0.145755069

Regards! 问候!

I am not so conversant in C#. 我不太熟悉C#。 But I don't think this problem would occur in Java because the default constructor of Random class uses a seed based on current time and a unique count identifier.Below is code from java.util.Random class. 但我不认为这个问题会在Java中发生,因为Random类的默认构造函数使用基于当前时间和唯一计数标识符的种子.Below是来自java.util.Random类的代码。

private static volatile long seedUniquifier = 8682522807148012L;
public Random() { this(++seedUniquifier + System.nanoTime()); }

If C# doesent support this out of box, you could use the above code to create a unique seed each time. 如果C#doesent支持这个开箱即用,您可以使用上面的代码每次创建一个唯一的种子。

PS: Note that since access to seedUniquifier is not synchronized, even though its volatile, there is a small possibility that same seeds are used for multiple Random objects. PS:请注意,由于对seedUniquifier的访问不同步,即使它是易失性的,也很可能将相同的种子用于多个Random对象。 From javadoc of Random class: 从Random类的javadoc:

"This constructor sets the seed of the random number generator to a value very likely to be distinct from any other invocation of this constructor." “这个构造函数将随机数生成器的种子设置为一个非常可能与此构造函数的任何其他调用不同 。”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM