我有一个随机数生成器如下。
uint64_t s[ 2 ];
uint64_t next(void) {
uint64_t s1 = s[ 0 ];
const uint64_t s0 = s[ 1 ];
s[ 0 ] = s0;
s1 ^= s1 << 23; // a
return ( s[ 1 ] = ( s1 ^ s0 ^ ( s1 >> 17 ) ^ ( s0 >> 26 ) ) ) + s0; // b, c
}
实际上,我希望在范围(0,1)中获得双打。一种选择是在我的代码中执行此操作
#define M_RAN_INVM64 5.42101086242752217003726400434970855e-20
[..]
double u1;
u1 = next()*M_RAN_INVM64;
一种选择是将next()转换为带符号的long long,乘以M_RAN_INVM64然后再加0.5。然后我可以添加2 ^(64)/ 2以确保我从未得到过0。
答案 0 :(得分:1)
已编辑:要将范围(0,1)中的任何正unsigned long long
转换为long double
,您可以使用以下步骤因素:
long double step = ((long double) 1.0) / ULLONG_MAX
其他信息在处理浮点数时,也许您可以考虑系统的限制。以下内容可以帮助您了解系统中的浮点数:
有一种可移植的方法来获取编译程序的系统中最小的浮点数。
这可以通过使用标准库<float.h>
来实现
有了它,您可以使用以下宏常量:
FLT_MIN // Smallest positive float number in your system
DBL_MIN // Smallest positive double number in your system
LDBL_MIN // Smallest positive long double number in your system
此外,您可以考虑类似“epsilon”的常量,它会为您提供有关给定类型的最小正数的信息,例如1.0!= 1.0 +“epsilon”。
当您尝试获得尽可能接近1.0的数字时,这可以帮助您,但仍然不同:
FLT_EPSILON
DBL_EPSILON
LDBL_EPSILON
例如,请参阅:float.h (ANSI)
答案 1 :(得分:1)
接受回答后:
double
个数字以对数方式分布。有double
0.25到0.5,因为有0.5到1.0 - 假设基数为2 double
。
假设double
是IEEE binary64:...
要在[0.0到1.0]范围内获得double
的均匀(线性)分布,只能使用2 ^ 53个值。因此,从next()
uint64_t u1 = next();
u1 >>= 11;
// or
u1 &= 0x001FFFFFFFFFFFFF;
if (u1 == 0) ThrowOutZero();
// convert to (0.0 to 1.0)
double d = u1 / 9007199254740992.0; // Divide by 2^53