我想得到 均匀分布 在范围[0.0,1.0)

如果可能的话,请让执行使用随机的字节 /dev/urandom.

这也将是好的,如果你的溶液 线安全.如果你不肯定的,请说明。

看看 一些解决方案 我以为关于后阅读其他的答案。

有帮助吗?

解决方案 2

这似乎是非常好的方式:

<代码>

unsigned short int r1, r2, r3;
// let r1, r2 and r3 hold random values
double result = ldexp(r1, -48) + ldexp(r2, -32) + ldexp(r3, -16);

这是基于NetBSD的drand48实现。

其他提示

简单的:一双有52位精度假如IEEE。所以产生有52位(或更大)的未签名的随机的整数(例如通过阅读字节dev/urandom),将其转换成一个双除2^(比特数,它是)。

这给数分布均匀(在于,该概率的价值在一定范围内是成比例的范围内)下,第52二进制数字。

复杂的:然而,有很多双值的范围[0,1)其上述无法产生。具体来说,一半的价值观的范围[0,0.5)(那些有他们最重要的位置)可能不会发生。四分之三的价值观的范围[0,0.25)(那些已经或者他们至少2位置)可能不会发生,等等,所有的方法只有一个积极的价值不少于2^在-5 1是可能的,尽管有一双能够代表squillions这种价值观。所以它不能说是真正统一的跨规定范围内以全面的精确度。

当然,我们不想选择其中之一倍与平等的概率,因为那时所得到的数字将上的平均值可能太小。我们仍然需要该概率的结果是在一定范围内是成比例的范围内,但具有较高的精确度在什么范围的工作。

想想 以下工作的。我没有特别研究或测试了这个算法(正如你可能会告诉你的方式有没有代码),而且就个人而言我不会用它没有找到适当的参考文献,表示它是有效的。但这里所说的:

  • 开始指数在52和选择52位的随机unsigned integer(假设的52位的尾数).
  • 如果最重要的位整数为0,增加指数一个,移的整数留下的一个,并填写的最低位在一个新的随机的位。
  • 重复,直到你撞到1中最重要的地方,或他人的指数变得太大了,你的双(1023.或者可能1022).
  • 如果你找到了一个1,把你的价值的2^指数。如果你得到了所有零,返回0(我知道,这实际上不是一种特殊的情况,但它担负着重强调如何以非常不可能的一个0回报[编辑:实际上它可能是一种特殊的情况-这取决于你是否不想产生denorms.如果没有,那么,一旦你有足够的0s在一排,你丢弃什么离开和返回0。但在实践中,这是因此不太可能,因为可以忽略不计,除非随机源码不是随机).

我不知道是否实际上有任何实际用于这样的一个随机的双重、头脑。你定义的随机应取决于一定程度上什么用的.但如果你可以从中受益的所有52个其重要的位是随机的,这实际上可能是有帮助的。

从文件中读取是线程安全的AFAIK,因此使用fopen()从/ dev / urandom读取将产生“真正随机”的字节。

虽然可能存在潜在的问题,但是将任何一组这样的字节作为整数访问,除以该大小的最大整数,将产生一个介于0和1之间的浮点值,大约是该分布。

例如:

FILE* f = fopen("/dev/urandom", "r");
int32_t int;
fread(&int, sizeof(int32_t), 1, f);
fclose(f);
double theRandomValue = int / (double) (2 ** 32 - 1);

诀窍是你需要一个符合你要求的54位随机数发生器。几行代码用一个联合来粘贴尾数中的54位,你有你的号码。诀窍不是双重浮动技巧是你想要的随机发生器。

#include <stdlib.h>
printf("%f\n", drand48());

的/ dev /随机:

double c;
fd = open("/dev/random", O_RDONLY);
unsigned int a, b;
read(fd, &a, sizeof(a));
read(fd, &b, sizeof(b));
if (a > b)
   c = fabs((double)b / (double)a);
else
    c = fabs((double)a / (double)b);

c是你的随机值

/ dev / urandom不是POSIX,通常不可用。

在[0,1]中均匀生成double的标准方法是生成[0,2 ^ N]范围内的整数并除以2 ^ N.因此,选择您最喜欢的随机数生成器并使用它。对于模拟,我的是 Mersenne Twister ,因为它非常快,但仍然没有很好的相关性。实际上,它可以为你做到这一点,甚至有一个版本可以为较小的数字提供更高的精度。通常,您可以给它一个种子,这有助于重复调试或向其他人展示您的结果。当然,如果没有指定,你可以让代码从/ dev / urandom中获取一个随机数作为种子。

出于加密目的,您应该使用其中一个标准加密库,例如 openssl )在可用时确实会使用/ dev / urandom。

至于线程安全,大多数都不会,至少使用标准接口,所以你需要在顶层构建一个层,或者只在一个线程中使用它们。线程安全的那些让你提供他们修改的状态,这样你就可以有效地运行多个不相互作用的随机数生成器,这可能不是你想要的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top