Я хотел бы выбрать несколько случайных битов из известной битовой маски. В идеале я хотел бы также выбирать эти биты в случайном порядке, но позже задачу можно разделить на выбор и перетасовку.
Некоторые дополнительные характеристики данных:
- битовая маска имеет длину 64 бита
- количество выбранных битов равно 4, 8, 16 или 32
- обычно устанавливается от 40 до 60 бит (всегда не менее половины)
- Мне нужны миллионы случайных вариантов для одной битовой маски (результаты используются для статистического моделирования)
Вот пример маски и вещей, которые я ожидаю (выбирая случайные 4 бита):
mask 0111111011111011111110111111111111111101111111100111101111111111
random4 ....1...........1........1...............1......................
shuffled bit positions: 41, 16, 4, 25
В этом примере я не должен возвращать битовую позицию 0, потому что она уже отключена.
Это известная горячая точка алгоритма, поэтому я хотел бы выжать из него как можно больше производительности (тест на случайный выбор занимает всего в ~ 2 раза больше времени, чем моя текущая реализация случайного выбора). Моя текущая идея состоит в том, чтобы заполнить первые n
числа в char positions[64]
позициями битов, установленных в битовой маске. Итак, для приведенного выше примера я бы получил: [1, 2, 3, 4, 5, 6, 8, 9, ...]
. Затем начните выбирать случайные числа между 0
и n
, чтобы выбрать случайную битовую позицию. После каждого выбора устанавливайте позицию на -1 и повторяйте случайный выбор, если я снова нажму -1.
Это отлично подходит для выбора 4 номеров, но слишком часто повторяется выбор при выборе 32 номеров.
Другая идея состоит в том, чтобы создать массив позиций, как указано выше, затем перемешать его с помощью Фишера-Йейтса и выбрать первые n
позиций. Это требует больше записей в массиве и всегда должно генерировать столько случайных чисел, сколько установлено битов, что может быть излишним для выбора только 4 битов.
Есть ли более быстрые способы генерировать эти данные? Я стремлюсь к точности симуляции, поэтому на самом деле речь идет о том, сколько случайных итераций я могу проверить за секунду.
Язык на самом деле не важен, но я думаю, что C будет доминировать здесь.