Я не уверен, что это ответ. Это определенно требует больше места, чем комментарий, поэтому я должен написать это здесь, но я хочу удалить, если другие считают это глупым.
Из OQ я получаю, что
- Биты энтропии очень дороги
- Все остальное следует считать дорогим, но не так, как энтропия.
Моя идея состоит в том, чтобы использовать двоичные цифры наполовину, четверть ... пространство maxValue, пока оно не уменьшится до числа. Что-то вроде
Я буду использовать maxValue = 333 (десятичное число) в качестве примера и приму функцию getBit()
, которая случайным образом возвращает 0 или 1
offset:=0
space:=maxValue
while (space>0)
//Right-shift the value, keeping the rightmost bit this should be
//efficient on x86 and x64, if coded in real code, not pseudocode
remains:=space & 1
part:=floor(space/2)
space:=part
//In the 333 example, part is now 166, but 2*166=332 If we were to simply chose one
//half of the space, we would be heavily biased towards the upper half, so in case
//we have a remains, we consume a bit of entropy to decide which half is bigger
if (remains)
if(getBit())
part++;
//Now we decide which half to chose, consuming a bit of entropy
if (getBit())
offset+=part;
//Exit condition: The remeinind number space=0 is guaranteed to be met
//In the 333 example, offset will be 0, 166 or 167, remaining space will be 166
}
randomResult:=offset
getBit()
может либо исходить из вашего источника энтропии, если он основан на битах, либо потреблять n бит энтропии сразу при первом вызове (очевидно, что n является оптимальным для вашего источника энтропии), и сдвигать его до пустой.