【问题标题】:Normalize random value of _int64标准化 _int64 的随机值
【发布时间】:2014-11-27 09:50:14
【问题描述】:

假设我们有来自函数的正态分布随机 int 值:

unsigned int myrand();

将其范围缩小到 [0, A] (int A) 的最常见方法是执行以下操作:

(double)rand() / UINT_MAX * A

现在我需要对 __int64 范围内的值执行相同的操作:

unsigned __int64 max64;
unsigned __int64 r64 = myrand();
r64 <<= 32;
r64 |= myrand();
r64 = normalize(r64, max64);

问题是通过一些 __int64 规范化返回范围,因为它不能放在双精度。由于性能原因,我不想将各种库用于大量数据。有没有办法在保存值的正态分布的同时快速轻松地缩小返回范围?

【问题讨论】:

    标签: c visual-c++ math


    【解决方案1】:

    你给的方法

    (double)myrand() / UINT_MAX * A
    

    已经坏了。例如,如果 A = 1 并且您想要 [0, 1] 范围内的整数,则只有在 myrand () 返回 UINT_MAX 时才能得到值 1。如果您的意思是范围 [0, A),也就是值 0,那么它仍然会被破坏,因为在这种情况下它将返回范围之外的值。无论如何,您都在引入偏见。

    如果您想要从 0 到 A(含)的 A+1 个不同值,并且 2^32 ≤ A

    第 1 步:像您一样计算一个 64 位随机数 R。如果 A 小于 2 的幂,则返回移动了正确数量的 R。

    第 2 步:找出有多少不同的随机值会映射到相同的输出值。从数学上讲,这个数字是地板 (2^64 / (A + 1))。 2^64 太大了,但这没问题,因为它等于 1 + floor ((2^64 - (A + 1)) / (A + 1)),在 C 或 C++ 中计算为 D = 1 + (- (A + 1)) / (A + 1) 如果 A 的类型为 uint64_t。

    第 3 步:通过计算 N = D * (A + 1) 找出应该映射多少个不同的随机值。如果 R >= N 则返回第 1 步。

    第 4 步:返回 R/D。

    不需要浮点运算。结果完全没有偏见。如果 A

    当然,除非 A 发生变化,否则您只计算一次 D 和 N。

    【讨论】:

    • 似乎是真的:) 缺点是在某些情况下我们需要多次生成随机数,尤其是当A变大时。
    【解决方案2】:

    如果您的平台可用,也许您可​​以使用“long double”。

    【讨论】:

    • shrink return range 怎么样?
    猜你喜欢
    • 2018-02-01
    • 1970-01-01
    • 2021-06-01
    • 2019-08-20
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多