Мне нужно сгенерировать около 9-100 миллионов неповторяющихся случайных чисел, от нуля до количества сгенерированных чисел, и мне нужно, чтобы они генерировались очень быстро. В нескольких ответах на похожие вопросы предлагалось просто перетасовать массив для получения случайных чисел, а в других предлагалось использовать фильтр Блума. Вопрос в том, какой из них более эффективен, и, если это фильтр Блума, как мне его использовать?
неповторяющиеся случайные числа
Ответы (2)
Вам вообще не нужны случайные числа. Вам нужны именно числа от 0 до N-1 в случайном порядке.
Простое заполнение массива и перетасовка должны быть очень быстрыми. Правильная перетасовка Фишера-Йейтса — это O(n), поэтому массив из 100 миллионов должен занять меньше секунды в C или даже в Java, немного медленнее в языке более высокого уровня, таком как Python.
Вам нужно только сгенерировать N-1 случайных чисел, чтобы выполнить перетасовку (возможно, до 1,3N, если вы используете выборку отклонения для достижения идеальной однородности), поэтому скорость будет во многом зависеть от того, насколько быстр ваш ГСЧ.
Вам никогда не придется искать, было ли уже сгенерировано число; это будет смертельно медленно, независимо от того, какой алгоритм вы используете, особенно ближе к концу прогона.
Если вам нужно чуть меньше N общих чисел, заполните массив от 0 до N-1, затем просто прервите перетасовку раньше и возьмите частичный результат. Только в том случае, если количество необходимых вам чисел очень мало по сравнению с их диапазоном, вы должны рассмотреть подход с генерацией и проверкой дубликатов. В этом случае алгоритм Боба Флойда может быть хорош.
В качестве альтернативы вы можете использовать блочный шифр соответствующего размера. Используйте блочный шифр, чтобы зашифровать числа 0, 1, 2, ..., и вы получите ряд неповторяющихся случайных чисел. Какая именно серия будет зависеть от используемого вами ключа. Они гарантированно не повторяются, потому что блочный шифр — это обратимая перестановка.
Для 64-битных номеров используйте DES, для 32-битных используйте Hasty Pudding (который допускает широкий диапазон размеров блоков) или напишите свой собственный простой шифр Фейстеля. Предполагая, что безопасность не является большой проблемой для этого, возможно написать свой собственный.