Андрей Карпати наткнулся на неочевидное поведение:
random.seed(5) и random.seed(-5) дают одинаковую последовательность случайных чисел.➡️ Как обнаружилось
Карпати работал над nanochat и хотел использовать знак seed'а для разделения train/test данных. Получил баг: train и test оказались идентичными.
➡️ Почему так
В исходниках CPython (
_randommodule.c, строка 321) явно вызывается abs():// "This algorithm relies on the number being unsigned"
n = PyNumber_Absolute(arg);
Знак просто отбрасывается.
➡️ Баг или фича?
Формально — не баг. Документация гарантирует только то, что одинаковый seed даст одинаковую последовательность. Но не гарантирует, что разные seed'ы дадут разные последовательности.
Карпати считает это ошибкой дизайна: знаковый бит мог бы удвоить пространство seed'ов. Простое решение:
n -> 2*abs(n) + int(n < 0).➡️ Что дальше
🔘Не полагаться на отрицательные seed'ы как на «другие»
🔘В NumPy отрицательные seed'ы вызывают ошибку — там строже
🔘Открыт issue на GitHub для обновления документации
import random
random.seed(42)
print(random.random()) # 0.6394267984578837
random.seed(-42)
print(random.random()) # 0.6394267984578837
@zen_of_python