Безопасно ли посеять Python ГСЧ с помощью поплавка? - PullRequest
2 голосов
/ 26 февраля 2020

Можно ли передавать значения с плавающей запятой в качестве аргумента функции random.seed ()? Вносит ли это непредвиденные проблемы?

Другими словами. Является ли ....

random.seed(0.99999999)
<use a few thousand random numbers>
random.seed(1)
<use a few thousand random numbers>

.... функционально эквивалентным ....

random.seed(0)
<use a few thousand random numbers>
random.seed(1)
<use a few thousand random numbers>

Быстрое тестирование показывает, что оба набора кода работают нормально и на поверхностном уровне выходы кажутся независимыми и детерминированными c.

Мне интересно знать, является ли этот метод посева полностью безопасным для использования в тех случаях, когда важна независимость между семенами. Получение детерминированных c результатов также важно. Я проверил некоторую документацию: Python 2.7 документация и Python 3.8 документация и сделал поиск в Google и нашел только ссылки на целые числа, используемые в качестве начального числа (или другие типы данных, которые преобразуются в целые числа). Я не видел ссылок на поплавки, и это заставляет меня задаться вопросом, являются ли они «безопасными» в том смысле, что они работают предсказуемым образом, без неприятных сюрпризов.

В настоящее время я работаю с Python 2.7, но мне интересен ответ и для более современных версий.

Ответы [ 2 ]

3 голосов
/ 26 февраля 2020

Использование числа с плавающей точкой в ​​качестве начального числа подразумевает функциональность:

Поддерживаемые типы начальных чисел: None, int, float, str, bytes и bytearray.

см. : https://github.com/python/cpython/blob/master/Lib/random.py#L156

Получение поплавка с одинаковым значением каждый раз имеет решающее значение для получения одного и того же семени, но это не так уж сложно. Самый надежный способ всегда получать одно и то же значение с плавающей запятой - это не выполнять какие-либо вычисления на нем или принимать какие-либо пользовательские данные. Если вы хотите обеспечить полный контроль, вы можете использовать struct.unpack для генерации числа из необработанных двоичных данных.

2 голосов
/ 26 февраля 2020

Да, безопасно использовать поплавок

Согласно документации , random.seed(a) использует a напрямую, если это int или long, в противном случае (если a не None) используется hash(a). Учитывая, что python требует, чтобы hash(x) == hash(y), если x == y, это означает, что такая же последовательность псевдослучайных чисел будет сгенерирована для равных чисел с плавающей точкой (со стандартными предостережениями о строгом сравнении чисел с плавающей запятой).

Документация python 3 менее понятна о том, как она обрабатывает вводы типов, отличных от int, str, bytes и bytearray, но само поведение аналогично python 2 для python 3,8 и ранее. Как упоминалось в ответе Аарона, посев на основе хеширования не рекомендуется в 3.9, но float продолжает оставаться поддерживаемым типом семени.

...