How to efficiently convert a few bytes into an integer between a range?

后端 未结 4 2141
离开以前
离开以前 2021-01-19 17:45

I\'m writing something that reads bytes (just a List) from a remote random number generation source that is extremely slow. For that and my personal

4条回答
  •  野性不改
    2021-01-19 18:14

    Unfortunately your Approach #1 is broken. For example if min is 0 and max 510, you'd add 2 bytes. There is only one way to get a 0 result: both bytes zero. The chance of this is (1/256)^2. However there are many ways to get other values, say 100 = 100+0, 99+1, 98+2... So the chance of a 100 is much larger: 101(1/256)^2.

    The more-or-less standard way to do what you want is to:

    Let R = max - min + 1   -- the number of possible random output values
    Let N = 2^k >= mR, m>=1  -- a power of 2 at least as big as some multiple of R that you choose.
    loop
       b = a random integer in 0..N-1 formed from k random bits
    while b >= mR -- reject b values that would bias the output
    return min + floor(b/m)
    

    This is called the method of rejection. It throws away randomly selected binary numbers that would bias the output. If min-max+1 happens to be a power of 2, then you'll have zero rejections.

    If you have m=1 and min-max+1 is just one more than a biggish power of 2, then rejections will be near half. In this case you'd definitely want bigger m.

    In general, bigger m values lead to fewer rejections, but of course they require slighly more bits per number. There is a probabilitistically optimal algorithm to pick m.

    Some of the other solutions presented here have problems, but I'm sorry right now I don't have time to comment. Maybe in a couple of days if there is interest.

提交回复
热议问题