Going from int values a=[0,N] to real values x=[0,1] has a fairly obvious algorithm:
x = a/N
Going the other way involves some rounding. We need to preserve the values:
0/N => 0, 1/N => 1, 2/N => 2, ..., 1 => N
But we have a choice of how we pick intermediate values. One way of doing it would be to divide the range [0,1] into (N+1) equal segments, so:
[0,1/(N+1) [1/(N+1),2/(N+1)) ... [(N-1)/(N+1),N/(N+1)) [N/(N+1),(N+1)/(N+1)]
This way of doing it has the nice property that the range [0,1] gets split up equally. Call this method #1.
Another way of doing it would be to use (N+1) segments centered on each of the points 0/N, 1/N, ... 1:
[-0.5/N,0.5/N) [0.5/N,1.5/N) ... [(N-1.5)/N,(N-0.5)/N) [(N-0.5)/N,(N+0.5)/N]
This doesn't preserve equal ranges, but has the elegant (if not particuarly useful?) property that the exact roundtrip values are in the middle of each range. Call this method #2.
There are infinitely many other methods that preserve the inverse mapping, but these are the interesting ones.
The combination of each method with the obvious integer => real method gives corresponding algorithms from going from [0,M] to [O,N]
Method #1:
b = floor (a*(N+1)/M); a < M. b = N; a == M.
Method #2:
b = floor (a*N/M+0.5)
How easy these are to code as integer algorithms depend on the values of N and M. If N+1 divides M+1 exactly (Eg, N=31, M=255), then method #1 is simple. The a < M case is:
b = floor (a*(N+1)/M) = floor (a*(N+1)/(M+1) + a*(N+1)/[(M+1)*M])
Since the second piece inside the floor() is less than (N+1)/(M+1) for a < M, and a == M works as a special case, we can write, for all a.
b = floor (a*(N+1)/(M+1))
But no similarly simple expression is available for method #2. On other other hand, for M = 255*255, N = 255, then method #1 is a little painful to compute as integers; the a < M case is:
b = floor (a*(256/(255*255))) = floor ((a/255 + a)/255) = floor ([floor(a/255) + a]/255)
Which involves quite few adds and shifts.
t = a + (a + (a >> 8)) >> 8 b = (t + (t >> 8)) >> 8
But method #2 works out nicely.
b = floor (a*255 / (255*255) + 0.5 * 255) = floor ((a+127.5)/255)
Which is easy to compute:
t = a + 127 b = (t + (t >> 8)) >> 8