You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何基于自制Linear Congruential Generator实现均匀与指数分布?

Implementing Uniform and Exponential Distributions with Your LCG

Great question! Let's walk through building these distributions using your existing Linear Congruential Generator (LCG) — first, let's recap your LCG's behavior since that's our foundation:

You're using the classic MINSTD_RAND parameters (multiplier 16807, modulus (2^{31}-1), which is 2147483647). This generator outputs values from 1 to 2147483646 (note: never initialize RN to 0, or it'll get stuck outputting 0 forever!).


1. Uniform Distribution Implementation

Uniform distributions come in two flavors: discrete (integer outputs) and continuous (floating-point). Since you mentioned wanting a long Module::... function, we'll start with discrete uniform, then add a continuous version for completeness.

Discrete Uniform (Integer Range [a, b])

This distribution gives every integer between a and b (inclusive) an equal chance of being selected. The key here is avoiding modulo bias — if we just take LCG() % range, some values will be slightly more likely if the LCG's output range isn't a perfect multiple of our target range.

Here's the implementation:

long Module::uniform_int(long a, long b) {
    const long MODULUS = 2147483647;
    const long MAX_LCG_OUTPUT = MODULUS - 1; // LCG outputs 1 to this value
    const long RANGE = b - a + 1;
    // Calculate upper limit to avoid bias: discard values above this
    const long LIMIT = MODULUS - (MODULUS % RANGE);

    long rn;
    do {
        rn = LCG(); // Get next LCG value
    } while (rn >= LIMIT); // Discard biased values

    return a + (rn % RANGE);
}
  • Parameters: a (lower bound) and b (upper bound), where a <= b
  • Mean: ((a + b) / 2) (for integers, this will be a floor/ceil value if the sum is odd)
  • Standard Deviation: (\sqrt{(RANGE^2 - 1)/12}) (the formula for discrete uniform variance)

Continuous Uniform (Floating-Point Range [low, high])

If you need a continuous uniform distribution (common for statistical simulations), we can normalize the LCG output to the [0,1) range first, then map it to your target interval:

double Module::uniform_double(double low, double high) {
    const long MODULUS = 2147483647;
    long rn = LCG();
    // Normalize LCG output to [1/MODULUS, 1) (no zero, which avoids edge cases later)
    double normalized = static_cast<double>(rn) / MODULUS;
    return low + normalized * (high - low);
}
  • Mean: ((low + high) / 2)
  • Standard Deviation: ((high - low)/\sqrt{12})

2. Exponential Distribution Implementation

Exponential distributions model waiting times (e.g., time between events) and use the inverse transform sampling method, which relies on a [0,1) uniform distribution. The probability density function is (f(x) = \lambda e^{-\lambda x}), where (\lambda) is the rate parameter (mean = (1/\lambda), standard deviation = (1/\lambda)).

Continuous Exponential Distribution

double Module::exponential(double lambda) {
    // Lambda must be positive! Add a check if you want to enforce this
    const long MODULUS = 2147483647;
    long rn = LCG();
    double u = static_cast<double>(rn) / MODULUS; // [1/MODULUS, 1)
    // Inverse CDF: -ln(u)/lambda (we can use u instead of 1-u since they're identical in distribution)
    return -log(u) / lambda;
}

If you need a long return type (e.g., integer waiting times), just floor the continuous result:

long Module::exponential_int(double lambda) {
    double exp_val = exponential(lambda);
    return static_cast<long>(floor(exp_val));
}

Critical Notes

  • Seed Initialization: Make sure you initialize RN to a non-zero value (e.g., RN = static_cast<long>(time(nullptr)) % 2147483646 + 1; — this ensures it's between 1 and 2147483646).
  • LCG Limitations: Your MINSTD_RAND has a period of (2^{31}-2), which is more than enough for most non-cryptographic use cases. If you need better randomness later, you could combine multiple LCGs, but this setup works perfectly for your current goals.

内容的提问来源于stack exchange,提问作者user9158336

火山引擎 最新活动