Не повторяя случайные числа в Objective C

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

Вы объявляете свои стили шрифтов в CSS, но некоторые машины Linux, некоторый Macs, некоторые мобильные браузеры - не будут иметь шрифта, который Вы определили. Это изменение приводит к отличающимся текстовым длинам и обертыванию. Тогда существует различие версий браузера и операционных систем, выполняющих каждого; как различные браузеры реализуют опции масштабирования; и размер текста может быть скорректирован конечным пользователем. Идентичный рендеринг является просто недостижимой целью.

, Но набираются храбрости! Это - "художественная" часть CSS: Способность быть гибким в Вашем дизайне, таким образом, что различия между браузерами, операционными системами и корректировками конечного пользователя обрабатываются изящно. Не боритесь за идентичный рендеринг - необходимо бороться за непротиворечивость бренда + соответствующий опыт + гибкость.

7
задан Cœur 29 December 2018 в 03:40
поделиться

5 ответов

Похоже, вы хотите перетасовать набор, а не "истинной" случайности. Просто создайте массив, в котором все позиции совпадают с числами, и инициализируйте счетчик:

num[ 0] =  0
num[ 1] =  1
: :
num[99] = 99
numNums = 100

Затем, когда вам нужно случайное число, используйте следующий метод:

idx = rnd (numNums);       // return value 0 through numNums-1
val = num[idx];            // get then number at that position.
num[idx] = val[numNums-1]; // remove it from pool by overwriting with highest
numNums--;                 //   and removing the highest position from pool.
return val;                // give it back to caller.

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

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

Функция AC, использующая статические значения, вроде этого должна помочь. Вызовите его с помощью

int i = myRandom (200);

, чтобы настроить пул (с любым числом, равным нулю или больше, указывающим размер), или

int i = myRandom (-1);

, чтобы получить следующее число из пула (достаточно любого отрицательного числа). Если функция не может выделить достаточно памяти, она вернет -2. Если в пуле не осталось номеров, он вернет -1 (в этот момент вы можете повторно инициализировать пул, если хотите). Вот функция с основным модулем тестирования, которую вы можете попробовать:

#include <stdio.h>
#include <stdlib.h>

#define ERR_NO_NUM -1
#define ERR_NO_MEM -2

int myRandom (int size) {
    int i, n;
    static int numNums = 0;
    static int *numArr = NULL;

    // Initialize with a specific size.

    if (size >= 0) {
        if (numArr != NULL)
            free (numArr);
        if ((numArr = malloc (sizeof(int) * size)) == NULL)
            return ERR_NO_MEM;
        for (i = 0; i  < size; i++)
            numArr[i] = i;
        numNums = size;
    }

    // Error if no numbers left in pool.

    if (numNums == 0)
       return ERR_NO_NUM;

    // Get random number from pool and remove it (rnd in this
    //   case returns a number between 0 and numNums-1 inclusive).

    n = rand() % numNums;
    i = numArr[n];
    numArr[n] = numArr[numNums-1];
    numNums--;
    if (numNums == 0) {
        free (numArr);
        numArr = 0;
    }

    return i;
}

int main (void) {
    int i;

    srand (time (NULL));
    i = myRandom (20);
    while (i >= 0) {
        printf ("Number = %3d\n", i);
        i = myRandom (-1);
    }
    printf ("Final  = %3d\n", i);
    return 0;
}

И вот результат одного запуска:

Number =  19
Number =  10
Number =   2
Number =  15
Number =   0
Number =   6
Number =   1
Number =   3
Number =  17
Number =  14
Number =  12
Number =  18
Number =   4
Number =   9
Number =   7
Number =   8
Number =  16
Number =   5
Number =  11
Number =  13
Final  =  -1

Имейте в виду, что, поскольку она использует статику, небезопасно вызывать из двух разных мест, если они хотят поддерживать свои собственные отдельные бассейны. Если бы это было так, статика была бы заменена буфером (счетчик хранения и пул), который «принадлежал» вызывающему (для этой цели можно было бы передать двойной указатель).

И, если вы: Если вам нужна версия для "нескольких пулов", я включил ее сюда для полноты картины.

#include <stdio.h>
#include <stdlib.h>

#define ERR_NO_NUM -1
#define ERR_NO_MEM -2

int myRandom (int size, int *ppPool[]) {
    int i, n;

    // Initialize with a specific size.

    if (size >= 0) {
        if (*ppPool != NULL)
            free (*ppPool);
        if ((*ppPool = malloc (sizeof(int) * (size + 1))) == NULL)
            return ERR_NO_MEM;
        (*ppPool)[0] = size;
        for (i = 0; i  < size; i++) {
            (*ppPool)[i+1] = i;
        }
    }

    // Error if no numbers left in pool.

    if (*ppPool == NULL)
       return ERR_NO_NUM;

    // Get random number from pool and remove it (rnd in this
    //   case returns a number between 0 and numNums-1 inclusive).

    n = rand() % (*ppPool)[0];
    i = (*ppPool)[n+1];
    (*ppPool)[n+1] = (*ppPool)[(*ppPool)[0]];
    (*ppPool)[0]--;
    if ((*ppPool)[0] == 0) {
        free (*ppPool);
        *ppPool = NULL;
    }

    return i;
}

int main (void) {
    int i;
    int *pPool;

    srand (time (NULL));
    pPool = NULL;
    i = myRandom (20, &pPool);
    while (i >= 0) {
        printf ("Number = %3d\n", i);
        i = myRandom (-1, &pPool);
    }
    printf ("Final  = %3d\n", i);
    return 0;
}

Как видно из модифицированного main () , вам нужно сначала инициализировать int указатель на NULL , затем передайте его адрес функции myRandom () . Это позволяет каждому клиенту (место в коде) иметь свой собственный пул, который автоматически выделяется и освобождается, хотя при желании вы все равно можете совместно использовать пулы.

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

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

0
ответ дан 6 December 2019 в 11:49
поделиться

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

0
ответ дан 6 December 2019 в 11:49
поделиться

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

Это объясняет предложения рандомизировать вывод компьютера путем перемешивания.

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

0
ответ дан 6 December 2019 в 11:49
поделиться

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

0
ответ дан 6 December 2019 в 11:49
поделиться