这个'randfloat()'是做什么的? 我看到一些C++代码: float randfloat(float a, float b) { uint32_t val = 0x3F800000 | (rng.getU32() >> 9); float fval = *(float *)(&val); return a + ((fval - 1.0f) * (b - a)); }

这个'randfloat()'是做什么的? 我看到一些C++代码: float randfloat(float a, float b) { uint32_t val = 0x3F800000 | (rng.getU32() >> 9); float fval = *(float *)(&val); return a + ((fval - 1.0f) * (b - a)); },c++,C++,完整的代码在一个屏幕上。它似乎是第一个按位或二进制数1111111 00000000000000000000000,带有一个右移9位的无符号随机整数 然后这些位被视为一个浮点数,然后变成一个浮点数?我猜它会返回一个浮点数,它是介于a和b之间的一个随机数,a包含和b排除。因此,代码的其他部分使用了randfloat(0.9,0.85),我认为它“几乎”与randfloat(0.85,0.9),除了第一种情况不包括0.85,而第二种情况不包括0.9 有人知道这部分是怎么回事吗?0x3F800000|

完整的代码在一个屏幕上。它似乎是第一个按位或二进制数
1111111 00000000000000000000000
,带有一个右移9位的无符号随机整数

然后这些位被视为一个浮点数,然后变成一个浮点数?我猜它会返回一个浮点数,它是介于
a
b
之间的一个随机数,
a
包含和
b
排除。因此,代码的其他部分使用了
randfloat(0.9,0.85)
,我认为它“几乎”与
randfloat(0.85,0.9)
,除了第一种情况不包括
0.85
,而第二种情况不包括
0.9


有人知道这部分是怎么回事吗?0x3F800000|(rng.getU32()>>9)并使其成为一个浮点数——是IEEE 754吗?

这看起来像是一个相当可怜的尝试,试图在间隔中检索一个随机数
[a,b)
这可能是无意中呈指数分布的,这取决于尾数和指数的排列方式,以及平台上
uint32\u t
的尾数。由于强制转换违反严格别名,代码的行为未定义

将其装箱并替换为

std::random_device rd;
std::mt19937 e(rd());
std::uniform_real_distribution<float> dist(a, b);   
dist(e); // a drawing
std::随机设备rd;
标准:MT19937E(rd());
标准:均匀实分布区(a,b);
距离(e);//图纸

这是可移植的,并且通过了很多随机性的统计测试。当然,前三条语句都与设置生成器有关-不要重复调用它。

在间隔中检索随机数看起来是一次相当可怜的尝试
[a,b)
这可能是无意中呈指数分布的,这取决于尾数和指数的排列方式,以及平台上
uint32\u t
的尾数。由于强制转换违反严格别名,代码的行为未定义

将其装箱并替换为

std::random_device rd;
std::mt19937 e(rd());
std::uniform_real_distribution<float> dist(a, b);   
dist(e); // a drawing
std::随机设备rd;
标准:MT19937E(rd());
标准:均匀实分布区(a,b);
距离(e);//图纸

这是可移植的,并且通过了很多随机性的统计测试。当然,前三个语句都与设置生成器有关-不要重复调用。下面尝试通过固定指数并填充随机有效值来形成[1.0f…2.0f]范围内的随机数

uint32_t val = 0x3F800000 | (rng.getU32() >> 9);
float fval = *(float *)(&val);
有很多

一个简单的选择是

float fval = (rng.getU32() >> 9)/8388608.0f;  // divide by 2^23


下面尝试通过固定指数并填充随机有效值来形成[1.0f…2.0f]范围内的随机数

uint32_t val = 0x3F800000 | (rng.getU32() >> 9);
float fval = *(float *)(&val);
有很多

一个简单的选择是

float fval = (rng.getU32() >> 9)/8388608.0f;  // divide by 2^23


0x3f800000
是以IEEE-754
binary32
单精度格式存储时的
1.0f
的二进制表示形式。此格式有23个存储的有效位(尾数)位。这些位由32位PRNG返回的23个高阶位填充,从而在[1,2).从结果中减去
1.0f
,得到[0,1]中的一个随机数,然后根据特定对
a
b
的舍入方式,将其缩放到区间[a,b]或[a,b]


正如其他人在评论中已经指出的那样,本代码中使用的类型双关语将
float
重新定义为
uint32\u t
是不安全的,因为它调用了未定义的行为。

0x3f80000
1.0f
的二进制表示,存储在IEEE-754
binary32
中,用于mat.此格式有23个存储的有效位(尾数)位。这些位由32位PRNG返回的23个高阶位填充,从而在[1,2]中产生伪随机数。从结果中减去
1.0f
,得到[0,1]中的随机数,然后将其缩放到间隔[a,b]或[1][a,b],取决于特定对
a
b
的舍入方式


正如其他人在评论中已经指出的那样,本代码中使用的类型双关语将一个
float
重新定义为
uint32\u t
是不安全的,因为它调用了未定义的行为。

不完全相关,但
*(float*)(&val);
调用未定义的行为。因此严格地说,整个函数调用的是substrict,严格地说是
float fval=*(float*)(&val)
是未定义的行为。可移植的替代方法是将
memcpy
val
转换为
fval
。您应该检查它们是否与
static\u assert(sizeof(val)==sizeof(fval))大小相同这在一些平台上是通用的…这实际上可能是任天堂交换机上运行的代码…但是提取代码的人可能把它移植到英特尔处理器和C++上,这些编译器通常可以编译和运行在MAC或PC上。老把戏可能最为人所知的是。它的意图似乎是将前9位设置为1,并将其余的位随机化。我相信在IEEE 754中,第一位是符号,接下来的8位是指数。假设这是目标表示,它看起来希望
fval
成为随机
浮点
,但设置了所有指数和符号位。这不是一种可移植的方法。但当Francois说“将前9位设置为1”是错误的时,最高的两位为零。不完全相关,但
*(float*)(&val);
调用未定义的行为。因此严格地说,整个函数调用的是substrically,严格地说
float fval=*(float*)(&val)
是未定义的行为。可移植的替代方法是将
memcpy
val
转换为
fval
。您应该检查它们是否与
static\u assert(sizeof(val)==sizeof(fval))一样大小;
。这是吗