3

For a project I am working on, I have access to a CSPRNG that outputs a random integer in the interval $[0, 2^n-1]$ for any integer $n$ greater than 0. I cannot use the zero values, so I have my RNG code in a while loop that runs until the random number is !==0. For small $n$ it is very likely that the while loop will run more than once, even more than twice (for $n=8$, the probability is $1/65536$). While this is not the bottleneck in my program, I want to eliminate the while loop and replace it with a linear transformation on the the generated random integer to get the integers I need in $[1, 2^n-1]$.

Is there a transformation that can be performed on the interval $[0, 2^n-1]$ to yield integers in $[1, 2^n-1]$ while retaining the uniform distribution of the random numbers?

(Would this be better posted in math.se?)

ampersand
  • 375
  • 2
  • 9

2 Answers2

6

Assuming that $n > 1$ so as to avoid a trivial special case, there is no function $g(\cdot)$ (linear or otherwise) that will transform a discrete random variable $X$ uniformly distributed on $\{0,1, 2, \ldots, 2^{n}-1\}$ into a discrete random variable $Y$ uniformly distributed in $\{1, 2, \ldots, 2^{n}-1\}$. This is because each value of $X$ has probability $2^{-n}$ attached to it, and this gets mapped onto the $Y$ value $g(X)$. Thus, for any $m \in \{1, 2, \ldots, 2^{n}-1\}$, $P\{Y=m\}$ is necessarily an integer multiple of $2^{-n}$ including, possibly, a zero multiple. It follows that the best one could do is to get a random variable $Y$ that takes on all values in $\{1, 2, \ldots, 2^{n}-1\}$ except one with equal probability $2^{-n}$, and this exceptional value occurs with probability $2\times2^{-n}=2^{-(n-1)}$.

On the other hand, if $X$ were a continuous random variable uniformly distributed on the interval $[0,2^n-1]$, the answer would be easy: $Y = 1+\frac{2^n-2}{2^n-1}X$ is a continuous random variable uniformly distributed on the interval $[1,2^n-1]$.

Dilip Sarwate
  • 2,801
  • 18
  • 25
3

No, there is no way to do it the way you want.

Just stick with the while loop. There is nothing wrong with using a while loop. As you seem to realize, the while loop will almost never execute more than one iteration, so it will perform extremely well. You don't say why you find the straightforward solution (the while loop) problematic, so I'm sticking with my answer: just use the while loop.

D.W.
  • 36,982
  • 13
  • 107
  • 196