C++ 从/dev/uradom获取浮点值
如何从C++ 从/dev/uradom获取浮点值,c++,c,linux,floating-point,C++,C,Linux,Floating Point,如何从/dev/uradom获取随机浮点值 如果我只是简单地使用一个cast,那么说: int fd = ::open("/dev/urandom", O_RDONLY); uint32_t n; read(fd, &n, sizeof(n)); float f = n; …我不确定是否能保证可移植性,因为我不知道n的大值是否一定能表示为f?MAXUINT是否保证可以表示为浮点值?您从/dev/uradom获得随机字节,但这些字节不一定会形成a)均匀分布的浮点值或b)甚至是任何对象的合
/dev/uradom
获取随机浮点值
如果我只是简单地使用一个cast,那么说:
int fd = ::open("/dev/urandom", O_RDONLY);
uint32_t n;
read(fd, &n, sizeof(n));
float f = n;
…我不确定是否能保证可移植性,因为我不知道
n
的大值是否一定能表示为f
?MAXUINT是否保证可以表示为浮点值?您从/dev/uradom获得随机字节,但这些字节不一定会形成a)均匀分布的浮点值或b)甚至是任何对象的合法表示。例如,在具有浮点或整数补漏白表示的平台上,您创建的值可能是补漏白表示,并且您将无法实际使用您创建的随机值
您只需验证库中的std::random\u device()
实现是否允许访问/dev/urandom(默认情况下,或者通过使用字符串参数,如:std::random\u device(“/dev/urandom”)
。然后您就有了一个随机数引擎,可以与例如std::uniform\u real\u distribution()一起使用
以获得所需的随机数分布
✓ libstdc++默认使用/dev/uradom:
✓ libc++也可以:
✗ Visual Studio的实现甚至没有使用非确定性RNG:
✓ 截至VS2012,MSDN声明“默认情况下生成的值是不确定的,并且是加密安全的”,可能是通过Windows的加密服务生成的
可以将随机字节直接读入浮点(例如float f;read(fd,&f,sizeof(f));
;假设IEEE-754,所有位模式都是有效的(尽管有两个无限位和许多安静的和信令的NaN)。您可以使用或来确定是否命中其中一个
当然,这是否合理取决于您想要的分布类型。假设IEEE-754float32
,您将在[0,2-126]非规范值和[2-126,2-125]、[2-125,2-124]、[2127,2128)正态值(及其反)的每个范围内获得均匀分布.您可以通过将随机整数除以最大整数值来获得随机数浮点
unsigned int RAND_MAX = 0xffffffff; // for 32 bit values
unsigned int random_value = rand_function();
double rand = (double) random_value / (double) RAND_MAX;
该随机数将介于0.0和1.0之间。
如果你想让它在某个范围内,就这样做:
double x = 1.0; // range start
double y = 3.5; // range end
double range = rand * (y - x) + x; // creates values between 1.0 and 3.5
我强烈怀疑您以这种方式构建的数字是否会均匀分布——您可能应该使用drand48()
等接口来构建随机浮点数。您想要什么范围的数字?通常的方法是执行以下问题所述的操作:(使用/dev/[u]正如您所建议的,随机的
,可能比调用rand()
更好,但概念是一样的。)使用@sarnold建议的drand48()
,看起来也是一个很好的解决方案-可能更好。@Mike:drand48()的缺点
是因为它使用了一种线性全等算法——适用于科学和大多数游戏用途,但不适用于加密级别的工作。/dev/uradom
在使用过程中重新填充了熵池——但浮点数的格式让我怀疑使用原始位填充数字的每个字段…@sarnold:vn
的值将均匀分布在0..4294967295范围内。将其分配给f
可能会失去一些精度,但它应该仍然均匀分布。是否确实需要0..4294967295范围内的浮点值是另一个问题。这个问题无法得到有意义的回答除非定义“随机浮点值”的含义.Uniform distribution或其他什么?什么范围?真令人惊讶。GNU libstdc++是正确的,LLVM libc++也是,但Visual Studio甚至无法接近。哦,得了吧,对于uint32\u t
,会有什么陷阱表示?并且将其分配给float
也不会引起问题。此外,assuming/dev/uradom
是统一的,那么浮点值将尽可能地统一,当然?@OliCharlesworth uint32\u t不会有陷阱表示,但int可能有陷阱表示。连接统一分布的字节将产生统一分布的两个补码或有符号大小整数考虑到在1和2之间有相同数目的IEEE 754浮点表示,在2和4之间。如果你得到一个整数并将其转换为浮点,则不会有失真,但是你会有超过某个值的失真会被“舍入”到S。当然,如果你把位重新解释为一个float
,这一点很重要。OP仅仅是分配给一个float
。我无法想象一种方法能在这个范围内得到更均匀的float
分布[-2^32,+2^32)。在我看来,您不太可能希望将uint32_t范围内的整数值表示为浮点数。我认为OP只是试图获取浮点数,而不打算局限于特定的分布。无论所需的分布是什么,它都更清晰,更不容易通过
分布。这会给你一个高度倾斜(因此可能完全不可用)的分布。@OliCharlesworth它会给你一个大致的指数分布。我在答案中解释了这一点。如果你想覆盖所有的实数,你还想要什么样的分布?“假设IEEE-754 float32,您将在[0,2-126)非规范值和[2-126,2-125]、[2-125,2-124]、[2127,2128)法线(及其否定值)的每个范围内获得均匀分布。”