如何在c++中生成随机浮点数?
我想我可以用整数rand除以某个数,这足够了吗?
如何在c++中生成随机浮点数?
我想我可以用整数rand除以某个数,这足够了吗?
当前回答
在现代c++中,你可以使用c++11附带的<random>头文件。 要获得随机浮点数,可以使用std::uniform_real_distribution<>。
你可以使用一个函数来生成数字,如果你不希望数字总是相同的,那就将引擎和分布设置为静态。 例子:
float get_random()
{
static std::default_random_engine e;
static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
return dis(e);
}
理想的做法是将浮动对象放置在std::vector:这样的容器中:
int main()
{
std::vector<float> nums;
for (int i{}; i != 5; ++i) // Generate 5 random floats
nums.emplace_back(get_random());
for (const auto& i : nums) std::cout << i << " ";
}
示例输出:
0.0518757 0.969106 0.0985112 0.0895674 0.895542
其他回答
rand()返回一个介于0和RAND_MAX之间的int值。要获得0.0到1.0之间的随机数,首先将rand()返回的int转换为浮点数,然后除以RAND_MAX。
如果您知道您的浮点数格式是IEEE 754(几乎所有现代cpu,包括Intel和ARM),那么您可以使用逐位方法从一个随机整数构建一个随机浮点数。只有当你无法访问c++ 11的random或Boost时,才应该考虑这样做。随机的,两者都更好。
float rand_float()
{
// returns a random value in the range [0.0-1.0)
// start with a bit pattern equating to 1.0
uint32_t pattern = 0x3f800000;
// get 23 bits of random integer
uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());
// replace the mantissa, resulting in a number [1.0-2.0)
pattern |= random23;
// convert from int to float without undefined behavior
assert(sizeof(float) == sizeof(uint32_t));
char buffer[sizeof(float)];
memcpy(buffer, &pattern, sizeof(float));
float f;
memcpy(&f, buffer, sizeof(float));
return f - 1.0;
}
这将比使用除法得到更好的分布。
如果您使用的是c++而不是C,那么请记住,在技术报告1 (TR1)和c++ 0x草案中,他们在头文件中添加了用于随机数生成器的功能,我相信它与Boost是相同的。随机库和绝对更灵活和“现代”比C库函数,兰德。
该语法提供了选择生成器(如mersenne twister mt19937)然后选择分布(正态分布、伯努利分布、二项式分布等)的能力。
语法如下(无耻地借用本网站):
#include <iostream>
#include <random>
...
std::tr1::mt19937 eng; // a core engine class
std::tr1::normal_distribution<float> dist;
for (int i = 0; i < 10; ++i)
std::cout << dist(eng) << std::endl;
对于c++,它可以在dist变量指定的范围内生成实浮点数
#include <random> //If it doesnt work then use #include <tr1/random>
#include <iostream>
using namespace std;
typedef std::tr1::ranlux64_base_01 Myeng;
typedef std::tr1::normal_distribution<double> Mydist;
int main() {
Myeng eng;
eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
Mydist dist(1,10);
dist.reset(); // discard any cached values
for (int i = 0; i < 10; i++)
{
std::cout << "a random value == " << (int)dist(eng) << std::endl;
}
return (0);
}
在我看来,上面的答案确实给出了一些“随机”浮点数,但它们都不是真正的随机浮点数(即它们错过了浮点数表示的一部分)。在我进入我的实现之前,让我们先看看浮点数的ANSI/IEEE标准格式:
|符号(1位)| e(8位)| f(23位)|
这个词代表的数字是 (-1 *号)* 2^e * 1.f
注意“e”是一个有偏差的数字(偏差为127),因此范围从-127到126。最简单的(实际上也是最随机的)函数是将随机int类型的数据写入浮点数,因此
int tmp = rand();
float f = (float)*((float*)&tmp);
注意,如果你做浮动f = (float)rand();它将整数转换为浮点数(因此10将变成10.0)。 现在如果你想限制最大值你可以这样做(不确定是否有效)
int tmp = rand();
float f = *((float*)&tmp);
tmp = (unsigned int)f // note float to int conversion!
tmp %= max_number;
f -= tmp;
但是如果你观察浮点数的结构,你会发现浮点数的最大值大约是2^127,这比int数的最大值(2^32)要大得多,因此排除了很大一部分可以用浮点数表示的数字。 这是我的最终实现:
/**
* Function generates a random float using the upper_bound float to determine
* the upper bound for the exponent and for the fractional part.
* @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
* @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
* @param sign_flag if sign_flag = 0 the random number is always positive, if
* sign_flag = 1 then the sign bit is random as well
* @return a random float
*/
float randf(int min_exp, int max_exp, char sign_flag) {
assert(min_exp <= max_exp);
int min_exp_mod = min_exp + 126;
int sign_mod = sign_flag + 1;
int frac_mod = (1 << 23);
int s = rand() % sign_mod; // note x % 1 = 0
int e = (rand() % max_exp) + min_exp_mod;
int f = rand() % frac_mod;
int tmp = (s << 31) | (e << 23) | f;
float r = (float)*((float*)(&tmp));
/** uncomment if you want to see the structure of the float. */
// printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);
return r;
}
使用这个函数randf(0,8,0)将返回一个介于0.0和255.0之间的随机数