规范化_int64的随机值

时间:2014-11-27 09:50:14

标签: c visual-c++ math

假设我们从函数中分配了随机int值:

unsigned int myrand();

将其范围缩小到[0,A](int A)的最常用方法是执行以下操作:

(double)rand() / UINT_MAX * A

现在我需要对__int64范围内的值执行相同的操作:

unsigned __int64 max64;
unsigned __int64 r64 = myrand();
r64 <<= 32;
r64 |= myrand();
r64 = normalize(r64, max64);

问题是通过某些__int64规范化返回范围,因为它不能放在double中。由于性能原因,我不想为大数字使用各种库。有没有办法快速,轻松地缩小返回范围,同时保存正常的值分布?

2 个答案:

答案 0 :(得分:1)

您提供的方法

(double)myrand() / UINT_MAX * A

已经坏了。例如,如果A = 1并且您希望整数在[0,1]范围内,那么如果myrand()返回UINT_MAX,则只能获得值1。如果你的意思是范围[0,A),那只是值0,那么它仍然会被破坏,因为在这种情况下它将返回一个超出范围的值。无论如何,你都在引入偏见。

如果你想要从0到A的A + 1个不同的值,并且2 ^32≤A&lt; 2 ^ 64,您按以下步骤操作:

步骤1:像您一样计算64位随机数R.如果A小于2的幂,则返回R偏移正确的量。

步骤2:查找将多少个不同的随机值映射到相同的输出值。在数学上,该数字是floor(2 ^ 64 /(A + 1))。 2 ^ 64太大了,但这没有问题,因为它等于1 + floor((2 ^ 64 - (A + 1))/(A + 1)),用C或C ++计算为D = 1 + ( - (A + 1))/(A + 1)如果A的类型为uint64_t。

步骤3:通过计算N = D *(A + 1)找出应该映射多少个不同的随机值。如果R> = N,则返回步骤1.

步骤4:返回R / D.

不需要浮点运算。结果完全没有偏见。如果A&lt; 2 ^ 32你回退到32位版本(或者你也使用64位版本,但它根据需要调用myrandom()两倍)。

当然,除非A发生变化,否则只计算一次D和N.

答案 1 :(得分:0)

如果你的平台上有可用的话,也许可以使用“long double”。