повышение:: случайный генерируют то же число каждый раз

Ранние версии JavaScript не позволили названные выражения function, и из-за этого мы не могли сделать выражение рекурсивной функции:

 // This snippet will work:
 function factorial(n) {
     return (!(n>1))? 1 : factorial(n-1)*n;
 }
 [1,2,3,4,5].map(factorial);


 // But this snippet will not:
 [1,2,3,4,5].map(function(n) {
     return (!(n>1))? 1 : /* what goes here? */ (n-1)*n;
 });

Для двигений это, arguments.callee было добавлено так, мы могли сделать:

 [1,2,3,4,5].map(function(n) {
     return (!(n>1))? 1 : arguments.callee(n-1)*n;
 });

Однако это было на самом деле действительно плохим решением, поскольку это (в сочетании с другими аргументами, вызываемым и проблемами вызывающей стороны) делает встраивание и хвостовую рекурсию невозможными в общем случае (можно достигнуть его в избранных случаях посредством трассировки и т.д., но даже лучший код sub оптимальный из-за проверок, которые иначе не были бы необходимы). Другая главная проблема - то, что рекурсивный вызов получит различное this значение, например:

var global = this;
var sillyFunction = function (recursed) {
    if (!recursed)
        return arguments.callee(true);
    if (this !== global)
        alert("This is: " + this);
    else
        alert("This is the global");
}
sillyFunction();

Во всяком случае, EcmaScript 3 решил эти вопросы путем разрешения названный выражениями function, например:

 [1,2,3,4,5].map(function factorial(n) {
     return (!(n>1))? 1 : factorial(n-1)*n;
 });

Это обладает многочисленными преимуществами:

  • функция может быть вызвана как любой другой из Вашего кода.

  • Это не загрязняет пространство имен.

  • значение this не изменяется.

  • Это более производительно (доступ , объект arguments является дорогим).

Возгласы,

Просто поняли, что в дополнение ко всему остальному вопрос был [приблизительно 118], или более конкретно Function.caller .

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

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

 function f(a, b, c, d, e) { return a ? b * c : d * e; }

, Если js интерпретатор не может гарантировать, что всеми обеспеченными аргументами являются числа в точке, что вызов выполняется, он должен или вставить проверки на все аргументы перед встроенным кодом, или он не может встроить функцию.

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

10
задан Kev 24 September 2012 в 21:53
поделиться

3 ответа

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

, вы найдете пример там , выдержка:

/*
 * Change seed to something else.
 *
 * Caveat: std::time(0) is not a very good truly-random seed.  When
 * called in rapid succession, it could return the same values, and
 * thus the same random number sequences could ensue.  If not the same
 * values are returned, the values differ only slightly in the
 * lowest bits.  A linear congruential generator with a small factor
 * wrapped in a uniform_smallint (see experiment) will produce the same
 * values for the first few iterations.   This is because uniform_smallint
 * takes only the highest bits of the generator, and the generator itself
 * needs a few iterations to spread the initial entropy from the lowest bits
 * to the whole state.
 */
generator.seed(static_cast<unsigned int>(std::time(0)));
13
ответ дан 3 December 2019 в 16:10
поделиться

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

В зависимости от того, что вы делаете с числами, вам может потребоваться добавить некоторые подумал о том, как выбрать начальную ценность. Если вам нужна высококачественная случайность (если вы генерируете криптографические ключи и хотите, чтобы они были достаточно безопасными), вам понадобится хорошее начальное значение. Если бы это был Posix, я бы предложил / dev / random - но вы рассчитываете использовать Windows, поэтому я не уверен, какой был бы хороший исходный источник.

Но если вы не возражаете против предсказуемого начального числа (для игр , моделирование и т. д.), быстрое и грязное начальное число - это текущая отметка времени, возвращаемая функцией time ().

6
ответ дан 3 December 2019 в 16:10
поделиться

Если вы работаете в системе 'nix, вы всегда можете попробовать что-то вроде этого;

int getSeed()
{
    ifstream rand("/dev/urandom");
    char tmp[sizeof(int)];
    rand.read(tmp,sizeof(int));
    rand.close();
    int* number = reinterpret_cast<int*>(tmp);
    return (*number);
}

Я предполагаю, что заполнение генератора случайных чисел таким способом быстрее, чем просто чтение / dev / urandom (или / dev / random ) для всех ваших потребностей в случайных числах.

5
ответ дан 3 December 2019 в 16:10
поделиться
Другие вопросы по тегам:

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