c - 如何将 unsigned long long 转换为 double

标签 c

我有一个随机数生成器,如下所示。

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) 范围内获得 double 。一种选择是在我的代码中执行此操作

#define M_RAN_INVM64 5.42101086242752217003726400434970855e-20
[..]
double u1;
u1 = next()*M_RAN_INVM64;
  1. 我担心我会失去精度,而且这取决于平台。
  2. 我不想得到值 0 或 1。

一个选项是将 next() 转换为 signed long long,乘以 M_RAN_INVM64,然后加 0.5。然后我可以添加 2^(64)/2 以确保我永远不会得到我认为的 0。

最佳答案

接受答案后:

double 数字呈对数分布。 double 0.25 到 0.5 的数量与 0.5 到 1.0 的数量一样多 - 假设基数为 2 double

假设 double 是 IEEE binary64:...

要在 [0.0 到 1.0) 范围内获得 double均匀(线性)分布,只能使用 2^53 个值。所以从 next()

的结果中丢掉 11 位
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

关于c - 如何将 unsigned long long 转换为 double,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24023799/

相关文章:

c - 哪个使用链表或静态数组?

c - FILE流缓冲区如何工作?

c - WinCE 应用程序的 Hello World(C 和 C++)- Visual Studio 2008

c - LLVM 字符串输入/输出

c - 我的动态数组有问题

c - 是否可以在 C 中创建自定义宽度的整数?

无法在基于 C 的 OpenCL 中创建子缓冲区

c - Mingw 和 Eclipse 无法找到库 - 2

c - 如何释放在函数中分配但地址由该函数返回的内存?

objective-c - 将 "hello world"扩展为 HelloWorld 的 C 预处理器宏