Случайные различия в поведении между C # и Java: семя - PullRequest
1 голос
/ 11 апреля 2009

У меня есть Random в классе, который предназначен для генерации случайных последовательностей в разных контекстах: это результат переноса из Java-кода. В версии Java все работает нормально, так как класс java.lang.Random имеет метод setSeed, который позволяет динамически изменять начальное значение.

Random rnd = new Random();
...
rnd.nextInt();
...
rnd.setSeed(seedValue);

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

К сожалению, в C # поведение сильно отличается, так как классу Random требуется, чтобы начальное число было установлено при построении:

Random rnd = new Random(seedValue);
...
rnd.Next();
...

Поэтому мне нужно каждый раз создавать новый экземпляр Random с заданным начальным числом, который в некоторых случаях генерирует то же значение, что и предыдущий вызов.

Это способ установить начальное значение экземпляра Random в C # динамически, без потери целостности экземпляра в глобальном масштабе?

Большое спасибо!

Ответы [ 3 ]

1 голос
/ 11 апреля 2009

Как правило, я создаю один экземпляр Random для своего приложения, и после установки начального числа при создании экземпляра я могу рассчитывать на каждый вызов Next, дающий мне новое случайное число. Хитрость заключается в том, чтобы убедиться, что семена как можно более случайны. Использование Random в приложении C # является хорошим примером того, где Singleton хорошо подходит.

Существует множество способов получить различную силу случайности в вашем семени, и есть несколько хороших вопросов SO, касающихся этого.

Пример ниже - подход, который я использую.

m_randomURL = "https://www.random.org/cgi-bin/randnum?num=1&min=1&max=1000000000";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(m_randomURL);
StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
Random rand = new Random(Convert.ToInt32(stIn.ReadToEnd()));

random.org использует атмосферный шум для генерации случайности и, по-видимому, используется для лотерей и тому подобного.

0 голосов
/ 11 апреля 2009

Прежде всего, я не ожидал бы, что setSeed будет вызываться более одного раза на Random во время выполнения. FreeCell делает это так, что вы можете «загрузить» игровые экземпляры, записав использованное начальное число.

Если вы меняете семена, это должно быть похоже на сброс Случайного экземпляра и, следовательно, не должно быть никакого конфликта, если вы его рестансирует. Random - это просто оболочка для базового алгоритма.

Если вы хотите получать разные результаты каждый раз (даже если вы используете setSeed), вы можете попробовать это:

class MyRandom {
  private Random random = new Random(DateTime.Now.Ticks);

  public void setSeed(long seed) {
    random = new Random(seed * this.random.next());
    ...

  public long next() {
    return random.next();
}

class MyClass {
  private MyRandom random = new MyRandom();
  public void Test() {
    random.setSeed(seedValue);
    int x = random.next();
    random.setSeed(seedValue);
    int y = random.next();
    // x,y will be different in most of the cases now
  }
}

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

0 голосов
/ 11 апреля 2009

попытаться обернуть случайный экземпляр как псевдокод:

class MyRandom {
   private Random random;

   public void setSeed(long seed) {
        random = new Random(seed);
        ...

   public long next() {
        return random.next();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...