简体   繁体   English

C#随机数生成器

[英]C# random number generator

I'm looking for a random number that always generates the same "random" number for a given seed. 我正在寻找一个始终为给定种子生成相同“随机”数的随机数。 The seed is defined by x + (y << 16) , where x and y are positions on a heightmap. 种子由x +(y << 16)定义 ,其中x和y是高度图上的位置。

I could create a new instance of System.Random every time with my seed, but thats a lot of GC pressure. 我可以每次用种子创建一个新的System.Random实例,但这会带来很大的GC压力。 Especially since this will be called a lot of times. 特别是因为这将被调用很多次。

EDIT: "A lot" means half a million times. 编辑:“很多”意味着五百万次。

Thanks to everyone that answered! 感谢所有回答! I know I was unclear, but I learned here that a hash function is exactly what I want. 我知道我不清楚,但是我在这里了解到哈希函数正是我想要的。

I could create a new instance of System.Random every time with my seed 我可以每次用种子创建一个新的System.Random实例。

Do that. 去做。

but thats a lot of GC pressure. 但是那是很大的GC压力。 Especially since this will be called a lot of times. 特别是因为这将被调用很多次。

How many times do you call it? 你叫多少次? Does it verifiably perform badly? 它可验证地表现不佳吗? Notice, the GC is optimized to deal with lots of small objects with short life time. 注意,GC经过优化,可以处理寿命短的许多小物体。 It should deal with this easily. 它应该轻松应对。

And, what would be the alternative that takes a seed but doesn't create a new instance of some object? 而且,采用种子但不创建某个对象的新实例的替代方案是什么? That sounds rather like a badly designed class, in fact. 实际上,这听起来像是一个设计不良的类。

Since a hash function is apparently closer to what you want, consider a variation of the following: 由于哈希函数显然更接近您想要的函数 ,因此请考虑以下内容的变体:

int Hash(int n) {
    const int prime = 1031;
    return (((n & 0xFFFF) * prime % 0xFFFF)) ^ (n >> 16);
}

This XORs the least significant two bytes with the most significant two bytes of a four-byte number after shuffling the least significant two byte around a little bit by multiplication with a prime number. 通过与质数相乘将最低有效的两个字节绕过一点后,此XOR将最低有效的两个字节与四字节数字中的最高有效的两个字节进行异或。 The result is thus in the range 0 < 0x10000 (ie it fits in an Int16). 因此,结果的范围为0 <0x10000(即,它适合Int16)。

This should “shuffle” the input number a bit, reliably produces the same value for the same input and looks “random”. 这应该稍微“混洗”输入数字,为相同的输入可靠地产生相同的值,并且看起来“随机”。 Now, I haven't done a stochastic analysis of the distribution and if ever a statistician was to look at it, he would probably go straight into anaphylactic shock. 现在,我还没有对分布进行随机分析,如果统计学家去研究它,他可能会直接引起过敏性休克。 (In fact, I have really written this implementation off the top of my head.) (实际上,我已经把这个实现写在脑子里了。)

If you require something less half-baked, consider using an established check sum (such as CRC32 ). 如果您需要一些半熟的东西,请考虑使用已建立的校验和(例如CRC32 )。

See Simple Random Number Generation for C# source code. 请参阅C#源代码的简单随机数生成 The state is just two unsigned integers, so it's easy to keep up with between calls. 状态只是两个无符号整数,因此很容易在两次调用之间保持同步。 And the generator passes standard tests for quality. 发电机通过了质量标准测试。

What about storing a Dictionary<int, int> the provides the first value returned by a new Random object for a given seed? 如何存储Dictionary<int, int>会提供给定种子的新Random对象返回的第一个值?

class RandomSource
{
    Dictionary<int, int> _dictionary = new Dictionary<int, int>();

    public int GetValue(int seed)
    {
        int value;
        if (!_dictionary.TryGetValue(seed, out value))
        {
            value = _dictionary[seed] = new Random(seed).Next();
        }

        return value;
    }
}

This incurs the GC pressue of constructing a new Random instance the first time you want a value for a particular seed, but every subsequent call with the same seed will retrieve a cached value instead. 一次需要特定种子的值时,这会导致GC构造新的Random实例的GC压力,但是随后每次使用相同种子的调用都将取回缓存的值。

I don't think a "random number generator" is actually what you're looking for. 我认为您实际上并不是在寻找“随机数生成器”。 Simply create another map and pre-populate it with random values. 只需创建另一个地图并使用随机值预先填充即可。 If your current heightmap is W x H, the simplest solution would be to create a W x H 2D array and just fill each element with a random value using System.Random. 如果您当前的高度图是W x H,最简单的解决方案是创建一个W x H 2D数组,然后使用System.Random用随机值填充每个元素。 You can then look up the pre-populated random value for a particular (x, y) coordinate whenever you need it. 然后,您可以在需要时查找特定(x,y)坐标的预填充随机值。

Alternatively, if your current heighmap actually stores some kind of data structure, you could modify that to store the random value in addition to the height value. 或者,如果您当前的高度图实际上存储某种数据结构,则可以对其进行修改以存储除高度值之外的随机值。

A side benefit that this has is that later, if you need to, you can perform operations over the entire "random" map to ensure that it has certain properties. 这样做的附带好处是,以后,如果需要,您可以对整个“随机”映射执行操作,以确保它具有某些属性。 For example, depending on the context (is this for a game?) you may find later that you want to smooth the randomness out across the map. 例如,根据上下文(这是否适用于游戏?),您稍后可能会发现想要平滑整个地图的随机性。 This is trivial if you precompute and store the values as I've described. 如果您按照我的描述预先计算并存储值,这将是微不足道的。

CSharpCity provides source to several random number generators. CSharpCity为多个随机数生成器提供了源。 You'll have to experiment to see whether these have less impact on performance than System.Random. 您必须进行实验,以查看它们是否对性能的影响小于System.Random。

ExtremeOptimization offers a library with several generators. ExtremeOptimization提供了一个包含多个生成器的库。 They also discuss quality and speed of the generators and compare against System.Random. 他们还讨论了发电机的质量和速度,并与System.Random进行了比较。

Finally, what do you mean by GC pressure? 最后,GC压力是什么意思? Do you really mean memory pressure, which is the only context I've seen it used in? 您真的是说内存压力,这是我所见过的唯一上下文吗? The job of the GC is to handle the creation and destruction of gobs of objects very efficiently. GC的工作是非常有效地处理对象料滴的创建和销毁。 I'm concerned that you're falling for the premature optimization temptation. 我担心您会因为过早的优化诱惑而陷入困境。 Perhaps you can create a test app that gives some cold, hard numbers. 也许您可以创建一个给出一些冷酷的数字的测试应用程序。

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

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