Как запросить семя, используемое random.random()?
Есть ли способ узнать, какое семя Python используется для засева его генератора случайных чисел?
Я знаю, что могу указать собственное семя, но я вполне доволен, что Python управляет им. Но, я хочу знать, какое семя оно использовало, так что, если мне нравятся результаты, которые я получаю в определенном запуске, я мог бы воспроизвести этот запуск позже. Если бы у меня было семя, которое было использовано, я бы мог.
Если ответ я не могу, то какой лучший способ генерировать семя? Я хочу, чтобы они всегда отличались от run to run --- Я просто хочу знать, что было использовано.
UPDATE: да, я имею в виду random.random()! ошибка... [название обновлено]
Ответы
Ответ 1
Невозможно получить автоматическое семя обратно от генератора. Обычно я генерирую такие семена:
seed = random.randrange(sys.maxsize)
rng = random.Random(seed)
print("Seed was:", seed)
Таким образом, это зависит от времени, поэтому каждый раз, когда вы запускаете script (вручную), он будет другим, но если вы используете несколько генераторов, у них не будет одинакового семени просто потому, что они были созданы почти одновременно.
Ответ 2
Состояние генератора случайных чисел не всегда является просто семенем. Например, безопасный PRNG обычно имеет энтропийный буфер, который представляет собой больший блок данных.
Однако вы можете сохранить и восстановить все состояние генератора числа randon, чтобы вы могли позже воспроизвести его результаты:
import random
old_state = random.getstate()
print random.random()
random.setstate(old_state)
print random.random()
# You can also restore the state into your own instance of the PRNG, to avoid
# thread-safety issues from using the default, global instance.
prng = random.Random()
prng.setstate(old_state)
print prng.random()
Результаты getstate
могут, конечно, быть маринованными, если вы хотите сохранить их настойчиво.
http://docs.python.org/library/random.html#random.getstate
Ответ 3
Вы можете подклассифицировать random.Random, переписать метод seed() так же, как это делает python (v3.5 в этом примере), но сохранить начальное значение в переменной перед вызовом super():
import random
class Random(random.Random):
def seed(self, a=None, version=2):
from os import urandom as _urandom
from hashlib import sha512 as _sha512
if a is None:
try:
# Seed with enough bytes to span the 19937 bit
# state space for the Mersenne Twister
a = int.from_bytes(_urandom(2500), 'big')
except NotImplementedError:
import time
a = int(time.time() * 256) # use fractional seconds
if version == 2:
if isinstance(a, (str, bytes, bytearray)):
if isinstance(a, str):
a = a.encode()
a += _sha512(a).digest()
a = int.from_bytes(a, 'big')
self._current_seed = a
super().seed(a)
def get_seed(self):
return self._current_seed
Если вы проверите его, первое случайное значение, сгенерированное с новым семенем, и второе значение, сгенерированное с использованием одного и того же семени (с созданным методом get_seed()), будет равно:
>>> rnd1 = Random()
>>> seed = rnd1.get_seed()
>>> v1 = rnd1.randint(1, 0x260)
>>> rnd2 = Random(seed)
>>> v2 = rnd2.randint(1, 0x260)
>>> v1 == v2
True
Если вы храните/копируете огромное начальное значение и пытаетесь использовать его в другом сеансе, генерируемое значение будет точно таким же.
Ответ 4
Семя - это внутренняя переменная в случайном пакете, которая используется для создания следующего случайного числа. Когда запрашивается новый номер, семя также обновляется.
Я бы просто использовал 0 в качестве семени, если вы хотите быть уверенным, что каждый раз должны иметь одинаковые случайные числа или настроить i.
В CorelDraw появился генератор случайных шаблонов, который был инициализирован семенем. Шаблоны сильно различались для разных семян, поэтому семена были важной конфигурационной информацией о шаблоне. Он должен быть частью параметров конфигурации для ваших прогонов.
EDIT: Как отмечено эфемерным, внутреннее состояние генератора случайных чисел может быть более сложным, чем семя, в зависимости от его реализации.
Ответ 5
Я хотел сделать то же самое, но я не мог получить семя. Итак, я думал, потому что семя генерируется со временем. Я создал свое семя, используя системное время, и использовал его как семя, поэтому теперь я знаю, какое семя было использовано.
SEED = int(time.time())
random.seed(SEED)
Ответ 6
Если вы "установите" семя с помощью random.seed(None)
, рандомизатор автоматически высевается как функция в системное время. Однако вы не можете получить доступ к этому значению, как вы заметили. Что я делаю, когда хочу рандомизировать, но все еще знаю, что это семя:
tim = datetime.datetime.now()
randseed = tim.hour*10000+tim.minute*100+tim.second
random.seed(randseed)
Примечание: причина, по которой я предпочитаю использовать time.time()
, как это было предложено @Abdallah, заключается в том, что таким образом randseed читается человеком и сразу понятен, что часто имеет большие преимущества. Компоненты даты и даже микросегменты также могут быть добавлены по мере необходимости.