Ускорение выборки `srand(time(NULL));`

есть рандом в диапазоне 0-8 (0,1,2,3,4,5,6,7,8) на вход приходит условие что результат может быть только 1 и 2 или 5 и7 или все кроме 2 или вообще любое сочетание( не все 9 значений или все, главное не одно ) вопрос в том чтобы быстро рандом срабатывал (например! когда нужно вернуть 2 или 5 очень долго перебирает чтобы вернуть либо 5 либо 2)

  m02:   int rnd; srand(time(NULL)); rnd = rand() % 9;
if ((rnd == 0) || (rnd == 2) || (rnd == 6) || (rnd == 8))
    {return rnd;} else { goto m02; }

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


Ответы (2 шт):

Автор решения: Stanislav Volodarskiy

В вашем коде есть неприятное место:

srand(time(NULL));
rnd = rand() % 9;

Этот код в течении одной секунды выдаёт одно и то же значение. time(NULL) выдаёт текущее время с разрешением в одну секунду. srand сбрасывает случайный генератор, затем вы спрашиваете первое случайное число. Если оно вас устраивает, то в течении секунды вы будете его выдавать снова и снова. Если число вас не устраивает, цикл будет ждать конца секунды. После чего процесс повторится.

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

#include <random>
#include <iostream>
#include <vector>

class Sampler {
public:
    int get_random(const std::vector<int> &values) {
        std::uniform_int_distribution<> distrib(0, values.size() - 1);
        return values[distrib(gen)];
    }
private:
    std::mt19937 gen;
};
 
int main() {
    const std::vector<int> digits = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
    Sampler s;
    for (int i = 0; i < 10000000; ++i) {
        std::cout << s.get_random(digits) << '\n';

    }
}

Десять миллионов случайных цифр в секунду:

$ g++ -std=c++17 -pedantic -Wall -Wextra -Werror -O3 slow-random.cpp

$ time ./a.out | wc -l
10000000

real  0m0.857s
user  0m0.872s
sys   0m0.024s
→ Ссылка
Автор решения: avp

Вы хотите в самом деле быстро?

Тогда упростите вывод результата, насколько возможно (переход от printf() к putchar() дает выигрыш в 5 раз)
(ну, и берите несколько маленьких чисел из одного вызова random() (улучшает время вдвое))

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

int
main (int ac, char *av[])
{
  int d[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};

  /* 1.  
  for (int i = 0; i < 10000000; i++)
    printf("%d\n", d[random() % 9]);

    avp@avp-desktop:~/avp/hashcode$ gcc ttt.c -O3
    avp@avp-desktop:~/avp/hashcode$ time ./a.out | wc -l
    10000000

    real        0m0.568s
    user        0m0.582s
    sys 0m0.025s

  */

  /* 2.
  for (int i = 0; i < 10000000; i++)
    putchar(d[random() % 9]+'0'), putchar('\n');

    avp@avp-desktop:~/avp/hashcode$ gcc ttt.c -O3
    avp@avp-desktop:~/avp/hashcode$ time ./a.out | wc -l
    10000000

    real        0m0.103s
    user        0m0.132s
    sys 0m0.013s

  */


  // А вот это в самом деле быстро
  for (int i = 0; i < 10000000 / 5; i++) {

    int r = random();
    for (int j = 0; j < 5; j++, r >> 5)
      putchar(d[(r & 0x1f) % 9] + '0'), putchar('\n');
  }
  /*
    avp@avp-desktop:~/avp/hashcode$ gcc ttt.c -O3
    avp@avp-desktop:~/avp/hashcode$ time ./a.out | wc -l
    10000000

    real        0m0.064s
    user        0m0.056s
    sys 0m0.049s
  */

  return 0;
}
→ Ссылка