Skip to main content
Explain about "debiasing"
Source Link
pepoluan
  • 275
  • 2
  • 12

I am in need of a "debiased" clamp function, to generate a uniformly-distributed random number from a good PRNG.

Let's assume that RNG in the below code is a field containing an instance of a good (or good enough) PRNG such as PCG, Xoshiro, or MT, which produced a reasonably-uniform distribution of random integers.

public int GetClamped(int maxnum) {
    // maxnum is totally arbitrary here, and likely not a power of 2
    int cap = int.MaxValue / maxnum * maxnum;
    int r;
    do {
        r = RNG.NextPositiveInt();  // Returns a value in the range [0, int.MaxValue]
    } while (r >= cap);
    return r >= maxnum ? r % maxnum : r;
}

I wonder if this can be optimized further, seeing I have 2 divisions and a multiplication there.


About "Debiasing"

Let's say a good PRNG returns a 16-bit value in the range of [0, 65535] with a uniform distribution.

If I clamp the value to 1000 and simply use the modulus % operator, the values in the range of [0, 535] after clamping will appear one time more often than the values in the range of [536, 999] (because there is no 65536, 65537 ... 65999)

This means that a simple clamping using the modulus % operator introduces a bias towards the lower range.

The algorithm above tries to find the largest value which will still satisfy the uniform distribution (64999) and discards all values above that cap to pull a new value from the PRNG.

The principle is that if [0, 65535] is uniform, then a truncated range of [0, 64999] will still be uniform. Hence the algorithm name of "unbiased clamping" or "debiased clamping".

Do note that the clamping value maxnum is arbitrary; it is not necessarily 1000 (like in this example), but can be any value in accordance to the user's needs. So, a precalculated table of "multiplicative equivalent to division" is simply not practical.

I am in need of a "debiased" clamp function, to generate a uniformly-distributed random number from a good PRNG.

Let's assume that RNG in the below code is a field containing an instance of a good (or good enough) PRNG such as PCG, Xoshiro, or MT, which produced a reasonably-uniform distribution of random integers.

public int GetClamped(int maxnum) {
    // maxnum is totally arbitrary here, and likely not a power of 2
    int cap = int.MaxValue / maxnum * maxnum;
    int r;
    do {
        r = RNG.NextPositiveInt();  // Returns a value in the range [0, int.MaxValue]
    } while (r >= cap);
    return r >= maxnum ? r % maxnum : r;
}

I wonder if this can be optimized further, seeing I have 2 divisions and a multiplication there.

I am in need of a "debiased" clamp function, to generate a uniformly-distributed random number from a good PRNG.

Let's assume that RNG in the below code is a field containing an instance of a good (or good enough) PRNG such as PCG, Xoshiro, or MT, which produced a reasonably-uniform distribution of random integers.

public int GetClamped(int maxnum) {
    // maxnum is totally arbitrary here, and likely not a power of 2
    int cap = int.MaxValue / maxnum * maxnum;
    int r;
    do {
        r = RNG.NextPositiveInt();  // Returns a value in the range [0, int.MaxValue]
    } while (r >= cap);
    return r >= maxnum ? r % maxnum : r;
}

I wonder if this can be optimized further, seeing I have 2 divisions and a multiplication there.


About "Debiasing"

Let's say a good PRNG returns a 16-bit value in the range of [0, 65535] with a uniform distribution.

If I clamp the value to 1000 and simply use the modulus % operator, the values in the range of [0, 535] after clamping will appear one time more often than the values in the range of [536, 999] (because there is no 65536, 65537 ... 65999)

This means that a simple clamping using the modulus % operator introduces a bias towards the lower range.

The algorithm above tries to find the largest value which will still satisfy the uniform distribution (64999) and discards all values above that cap to pull a new value from the PRNG.

The principle is that if [0, 65535] is uniform, then a truncated range of [0, 64999] will still be uniform. Hence the algorithm name of "unbiased clamping" or "debiased clamping".

Do note that the clamping value maxnum is arbitrary; it is not necessarily 1000 (like in this example), but can be any value in accordance to the user's needs. So, a precalculated table of "multiplicative equivalent to division" is simply not practical.

Source Link
pepoluan
  • 275
  • 2
  • 12

C# Debiasing from Good PRNG

I am in need of a "debiased" clamp function, to generate a uniformly-distributed random number from a good PRNG.

Let's assume that RNG in the below code is a field containing an instance of a good (or good enough) PRNG such as PCG, Xoshiro, or MT, which produced a reasonably-uniform distribution of random integers.

public int GetClamped(int maxnum) {
    // maxnum is totally arbitrary here, and likely not a power of 2
    int cap = int.MaxValue / maxnum * maxnum;
    int r;
    do {
        r = RNG.NextPositiveInt();  // Returns a value in the range [0, int.MaxValue]
    } while (r >= cap);
    return r >= maxnum ? r % maxnum : r;
}

I wonder if this can be optimized further, seeing I have 2 divisions and a multiplication there.