Во-первых;Следует понимать, что (для генерации случайных чисел) по модулю "не степень 2" вызывает смещение и его следует избегать.Например, если вы хотите число от 0 до 2 и начните с 4-битного случайного числа (значения 0, 1, 2, .., 14, 15), то после «по модулю 3» значения станут 0, 0, 0, 1, 1, 1, ..., 4, 4, 4, 5) и значение 5 будет намного менее вероятным, чем любое другое значение.
Самый простой способ исправить "смещение, вызванноепо модулю non-power of 2 "означает маскирование (с AND) до следующей наибольшей степени 2 минус 1, затем сбросьте число и повторите попытку, если значение все еще находится вне диапазона.Например, если вы хотите число от 0 до 2 и начните с 32-битного случайного числа;вы должны сделать «число = число & (4-1)» (потому что 4 является следующей по величине степенью 2), а затем, если число больше 2, вы отбросите его и снова получите совершенно новое случайное число.
Сейчас ...
Если вы пытаетесь избежать "смещения, вызванного по модулю не-силы 2";почему бы не повторить попытку, если число оказалось четным в диапазоне от 162 до 278?
Например (в C):
#define MAX_VALUE 500
#define NEXT_POWER_OF_2 512
int getNumber(void) {
int number;
do {
number = rand();
number = number & (NEXT_POWER_OF_2 - 1);
} while( (number > MAX_VALUE) || ((number >= 162) && (number <= 278) && (number & 1 == 0)) );
}
Для сборки:
;Input
; none
;
;Output
; eax = random number in range from 0 to MAX_NUMBER that is not an even number from 168 to 278
%define MAX_VALUE 500
%define NEXT_POWER_OF_2 512
getNumber:
call getRandomDword ;eax = random 32-bit value
and eax,NEXT_POWER_OF_2-1 ;eax = random N-bit value
cmp eax,MAX_VALUE ;Is it too large?
ja getNumber ; yes, retry
cmp eax,278 ;Is it larger than the "not even" range?
ja .done ; yes, allow the number
cmp eax,162 ;Is it smaller than the "not even" range?
jb .done ; yes, allow the number
test al,1 ;Is it even?
je getNumber ; yes, retry
.done:
ret
Примечание: я понятия не имею, нужен ли вам 16-битный, 32-битный или 64-битный код, или должен ли код работать на каких процессорах или каков источник случайности.Например, последние процессоры поддерживают инструкцию rdrand
, которая является относительно медленной (она предназначена для криптографии, а не для скорости, но может использоваться для регулярного «повторного заполнения» генератора псевдослучайных чисел), но если вам нужно убедиться, что код работаетхорошо на старом 80386 тогда ...