Насколько хороший java.util. Случайный?

Обновление: Java 9 Stream теперь поставляется с методом takeWhile .

Нет необходимости в хаках или других решениях. Просто используйте это!


Я уверен, что это может быть значительно улучшено: (кто-то может сделать его потокобезопасным, возможно)

Stream stream = Stream.iterate(0, n -> n + 1);

TakeWhile.stream(stream, n -> n < 10000)
         .forEach(n -> System.out.print((n == 0 ? "" + n : "," + n)));

Взломать наверняка .. Не элегантный - но он работает ~: D

class TakeWhile implements Iterator {

    private final Iterator iterator;
    private final Predicate predicate;
    private volatile T next;
    private volatile boolean keepGoing = true;

    public TakeWhile(Stream s, Predicate p) {
        this.iterator = s.iterator();
        this.predicate = p;
    }

    @Override
    public boolean hasNext() {
        if (!keepGoing) {
            return false;
        }
        if (next != null) {
            return true;
        }
        if (iterator.hasNext()) {
            next = iterator.next();
            keepGoing = predicate.test(next);
            if (!keepGoing) {
                next = null;
            }
        }
        return next != null;
    }

    @Override
    public T next() {
        if (next == null) {
            if (!hasNext()) {
                throw new NoSuchElementException("Sorry. Nothing for you.");
            }
        }
        T temp = next;
        next = null;
        return temp;
    }

    public static  Stream stream(Stream s, Predicate p) {
        TakeWhile tw = new TakeWhile(s, p);
        Spliterator split = Spliterators.spliterator(tw, Integer.MAX_VALUE, Spliterator.ORDERED);
        return StreamSupport.stream(split, false);
    }

}

47
задан Dove 17 January 2009 в 16:23
поделиться

5 ответов

В некоторой степени генераторы случайных чисел являются лошадями для курсов. Случайный класс реализует LCG с обоснованно выбранными параметрами. Но это все еще показывает следующие функции:

, Если эти вещи не будут иметь значения для Вас, то Случайный имеет плюс того, чтобы быть обеспеченным как часть JDK. Это достаточно хорошо для вещей как случайные игры (но не, где деньги включены). Нет никаких слабых семян как таковых.

Другая альтернатива, которая является генератор XORShift , который может быть реализован в Java следующим образом:

public long randomLong() {
  x ^= (x << 21);
  x ^= (x >>> 35);
  x ^= (x << 4);
  return x;
}

Для некоторых очень дешевых операций, это имеет период 2^64-1 (нуль не разрешен), и достаточно просто быть встроенным, когда Вы генерация значения неоднократно. Различные значения сдвига возможны: см. статью George Marsaglia о Генераторах XORShift для получения дополнительной информации. Можно считать биты в числах сгенерированными как являющийся одинаково случайным. Одна основная слабость - то, что иногда это будет входить в "колею", где не много битов установлены в числе, и затем требуется несколько поколений для выхода из этой колеи.

Другие возможности:

  • комбинируют различные генераторы (например, подают вывод от генератора XORShift в LCG, затем добавляют результат к выводу генератора XORShift с различными параметрами): это обычно позволяет слабым местам различных методов быть "сглаженными" и может дать более длительный период, если периоды комбинированных генераторов тщательно выбраны
  • , добавляет "задержка" (для предоставления более длительного периода): по существу, где генератор обычно преобразовывал бы последнее сгенерированное число, сохраните "буфер истории" и преобразуйте, скажем, (n-1023) th.

я сказал бы, избегают генераторов, которые используют глупый объем памяти, чтобы дать Вам период дольше, чем Вам действительно нужно (у некоторых есть период, больше, чем количество атомов во вселенной - Вам действительно обычно не нужно это). И обратите внимание, что "длительный период" не обязательно означает "высококачественный генератор" (хотя 2^48 является все еще немного низким!).

51
ответ дан Neil Coffey 7 November 2019 в 23:28
поделиться

Поскольку zvrba сказал, что JavaDoc объясняет нормальную реализацию. Страница Wikipedia на генераторах псевдослучайного числа имеет изрядное количество информации и упоминает вихрь Мерсенна , который не считают криптографически безопасным, но очень быстр и имеет различный реализации в Java. (Последняя ссылка имеет две реализации - существуют доступные другие, я верю.)

, Если Вы должны криптографически защитить поколение, прочитайте страницу Wikipedia - существуют доступные различные варианты.

10
ответ дан Jon Skeet 7 November 2019 в 23:28
поделиться

Это описано в документация . Линейные congruential генераторы теоретически хорошо поняты, и много материала по ним доступно в литературе и в Интернете. Линейный congruential генератор с теми же параметрами всегда производит ту же периодическую последовательность, и единственная вещь, которую решает семя, состоит в том, где последовательность начинается. Таким образом, ответ на Ваш первый вопрос "да, при генерации достаточных случайных чисел".

4
ответ дан zvrba 7 November 2019 в 23:28
поделиться

Когда RNGs идут, реализация Sun определенно не современная , but's, достаточно хороший в большинстве целей. Если Вам нужны случайные числа в целях криптографии, существует java.security. SecureRandom, если Вы просто хотите что-то быстрее и лучше, чем java.util.random, легко найти реализации Java вихря Мерсенна в сети.

6
ответ дан Michael Borgwardt 7 November 2019 в 23:28
поделиться

Если бы качество RNG действительно имеет значение для Вас, я рекомендовал бы использовать Ваш собственный RNG. Возможно, java.util. Случайный является просто большим, в этой версии, в Вашей операционной системе, и т.д. Это, вероятно. Но это могло измениться. Это произошло перед этим писатель библиотеки, сделанный вещами, хуже в более поздней версии.

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

, Если Вы не реализуете свое собственное, можно захватить код для известного RNG из уважаемого источника и использовать его в проектах. Тогда никто не изменит Ваш генератор из-под Вас.

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

-2
ответ дан John D. Cook 7 November 2019 в 23:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: