как запросить семя, используемое random.random()?

есть ли способ узнать, какое семя Python использовал для посева своего генератора случайных чисел?

Я знаю, что могу указать свое собственное семя, но я вполне доволен управлением Python. Но я хочу знать, какое семя оно использовало, чтобы, если мне понравятся результаты, которые я получу в конкретном прогоне, я мог бы воспроизвести этот прогон позже. Если бы у меня было семя, которое было использовано, тогда я мог бы.

Если ответ я не могу, то какой лучший способ создать семя сам? Я хочу, чтобы они всегда Отличайтесь от run to run-я просто хочу знать, что было использовано.

UPDATE: да, я имею в виду случайный.random()! ошибка... [название обновлено]

7 ответов


не возможно получить автоматическое семя назад вне от генератора. Обычно я генерирую такие семена:

seed = random.randrange(sys.maxsize)
rng = random.Random(seed)
print("Seed was:", seed)

таким образом, он основан на времени, поэтому каждый раз, когда вы запускаете скрипт (вручную), он будет отличаться, но если вы используете несколько генераторов, у них не будет одного и того же семени просто потому, что они были созданы почти одновременно.


состояние генератора случайных чисел не всегда просто семя. Например, защищенный PRNG обычно имеет буфер энтропии, который является большим блоком данных.

Вы можете, однако, сохранить и восстановить все состояние генератора чисел Рандон, так что вы можете воспроизвести его результаты позже:

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


Вы можете подкласс случайный.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

Если вы храните / копируете огромное начальное значение и пытаетесь использовать его в другом сеансе, генерируемое значение будет точно так же.


Если вы" установите " семя с помощью random.seed(None), рандомизатор автоматически засевается как функция системного времени. Однако, как вы заметили, вы не можете получить доступ к этому значению. Что я делаю, когда хочу рандомизировать, но все еще знаю, что семя таково:

tim = datetime.datetime.now()
randseed = tim.hour*10000+tim.minute*100+tim.second
random.seed(randseed)

Примечание: причина, по которой я предпочитаю это с помощью time.time() как предложил @Abdallah, потому что таким образом randseed читается человеком и сразу понятно, что часто имеет большие преимущества. Компоненты даты и даже microsegments может также быть добавлен по мере необходимости.


семя является внутренней переменной в случайном пакет, который используется для создания следующего случайного числа. Когда запрашивается новый номер, семя также обновляется.

Я бы просто использовал 0 в качестве семени, если вы хотите иметь одинаковые случайные числа каждый раз или сделать I настраиваемым.

У CorelDraw когда-то был генератор случайных шаблонов, который был инициализирован семенем. Образцы сильно различались для разных семян, поэтому семя было важно информация о конфигурации шаблона. Это должно быть частью параметров конфигурации для ваших запусков.

EDIT: как отметил эфемерный, внутреннее состояние генератора случайных чисел может быть более сложным, чем семя, в зависимости от его реализации.


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

SEED = int(time.time())
random.seed(SEED)

поскольку никто не упомянул, что обычно лучшая случайная выборка, которую вы можете получить на любом языке программирования, генерируется через операционную систему, я должен предоставить следующий код:

random_data = os.urandom(8)
seed = int.from_bytes(random_data, byteorder="big")

это криптографически безопасной.

источник: https://www.quora.com/What-is-the-best-way-to-generate-random-seeds-in-python


со значением 8 он, похоже, производит примерно такое же количество цифр, как sys.maxsize для мне.

>>> int.from_bytes(os.urandom(8), byteorder="big")
17520563261454622261
>>> sys.maxsize
9223372036854775807
>>>