对于唯一浮点值的有效随机数生成器我想更多地了解浮点值。我将把问题分成两部分。
我正在寻找该方法的实现:
size_t numOfFloats(const float min, const float max);
考虑到数据类型的最大精度,它会考虑所有可能的浮点值。
我正在寻找该方法的实现:
vector<float> enumAllFloats(const float min, const float max);
返回的向量的大小应始终等于我第一个问题的方法的返回值。
如果需要,允许使用C ++ 11.
答案 0 :(得分:9)
您可以使用nextafterf枚举所有可表示的浮点数:
vector<float> enumAllFloats(const float tmin, const float tmax) {
vector<float> res;
for (float x = tmin; x < tmax; x = nextafterf(x, tmax))
res.push_back(x);
res.push_back(tmax);
return res;
}
答案 1 :(得分:4)
您可以使用浮点数的ieee754表示将它们映射到int。然后,用int进行数学运算。
注意以下代码不适用于负数,并且不考虑特殊浮点值(NaN,无穷大......)
size_t numOfFloats(const float min, const float max){
// assert 0 <= min <= max
// assert sizeof(float) == sizeof(int32_t)
const int32_t min_i = *reinterpret_cast<const int32_t*>(&min);
const int32_t max_i = *reinterpret_cast<const int32_t*>(&max);
return max_i-min_i+1;
}
此外,当您知道带有整数的映射时,可以轻松列出它们:
void print_successive_floats(const float min, const float max){
const int32_t min_i = *reinterpret_cast<const int32_t*>(&min);
const int32_t max_i = *reinterpret_cast<const int32_t*>(&max);
for(int32_t i = min_i; i<=max_i; ++i){
float f = *reinterpret_cast<float*>(&i);
std::cout << f << std::endl;
}
}
为了完整性,为了匹配您的API:
vector<float> enumAllFloats(const float min, const float max){
vector<float> out;
out.reserve(numOfFloats(min, max));
const int32_t min_i = *reinterpret_cast<const int32_t*>(&min);
const int32_t max_i = *reinterpret_cast<const int32_t*>(&max);
for(int32_t i = min_i; i<=max_i; ++i){
float f = *reinterpret_cast<float*>(&i);
out.push_back(f);
}
return out;
}
谨防巨大的载体=)
答案 2 :(得分:3)
我假设您的目标架构使用浮点数的IEEE标准IEEE表示(IEEE754,如果我没有记错的话)。
此表示的一个属性是相同符号的相邻浮点数具有相邻表示形式,即如果将某些float
的(32位)二进制表示形式视为(32位){{ 1}},相同符号的相邻浮点数将使相应的int
相差一个。
因此,如果您的int
和min
符号相同,那么您可以将它们转换为max
,然后进行简单循环。
类似的东西(代码改编自here,我也建议作为更多信息的来源):
int
如果/* See
https://randomascii.wordpress.com/2012/01/11/tricks-with-the-floating-point-format/
for the potential portability problems with the union and bit-fields below.
*/
union Float_t
{
int32_t i;
float f;
};
vector<float> enumAllFloats(const float min, const float max) {
std::vector<float> result;
Float_t fl;
fl.f = min;
result.push_back(fl.f);
for (; fl.f <= max; fl.i++)
result.push_back(fl.f);
return result;
}
和min
有不同的符号,则必须分别在范围的正负部分循环。此外,如果两者都是否定的,您可能需要将max
和min
换成上面的代码。
但是,如果您确实想将它用于RNG,请注意,因为这些浮动不会在max
范围内均匀分布。