How can I generate a random BigInteger within a certain range?

后端 未结 6 2408
春和景丽
春和景丽 2021-02-13 06:52

Consider this method that works well:

public static bool mightBePrime(int N) {
    BigInteger a = rGen.Next (1, N-1);
    return modExp (a, N - 1, N) == 1;
}
         


        
6条回答
  •  无人共我
    2021-02-13 07:24

    The naive implementation will fail on average 64 times before finding a valid BigInteger within the specified range.

    On the worst case, my implementation will retry on average only 0.5 times (read as: 50% of the times it will find a result on the first try).

    Also, unlike with modular arithmetic, my implementation maintains a uniform distribution.

    Explanation

    We must generate a random BigInteger between min and max.

    1. If min > max, we swap min with max
    2. To simplify the implementation we shift our range from [min, max] to [0, max-min], this way we won't have to deal with the sign bit
    3. We count how many bytes max contains (bytes.Length)
    4. From the most significant bit, we count how many bits are 0 (zeroBits)
    5. We generate a random sequence of bytes.Length bytes
    6. We know that for our sequence to be < max, at least zeroBits bits from the most significant bit must be 0, so we use a zeroBitMask to set them with a single bit-to-bit & operation over the most significant byte, this will save a lot of time by reducing the change of generating a number out of our range
    7. We check if the number we generated is > max, and if so we try again
    8. We unshift the range back from [0, max-min] to [min, max] by adding min to our result

    And we have our number.

提交回复
热议问题