Случайные числа: rand и srand
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
int dice = rand() % 6 + 1;
int x = rand() % 101;
int y = rand() % (50 - 10 + 1) + 10;
printf("Кубик: %d\n", dice);
printf("От 0 до 100: %d\n", x);
printf("От 10 до 50: %d\n", y);
return 0;
}Результат при каждом запуске свой, поэтому здесь он не показан.
rand()возвращает псевдослучайное (вычисленное по формуле, но похожее на случайное) целое от 0 доRAND_MAX. Это число не меньше 32767: в Windows оно ровно 32767, в Linux — 2 147 483 647.srand(начальное_число)задаёт, с чего начнётся последовательность.time(NULL)— текущее время в секундах, поэтому каждый запуск начинается по-разному.rand() % n— число от 0 доn − 1. Отсюда формула для диапазона от a до b включительно:rand() % (b - a + 1) + a.
Почему числа одинаковые при каждом запуске
Без srand генератор всегда начинает с одного и того же места (как после srand(1)), и программа при каждом запуске выдаёт ту же «случайную» последовательность. Добавьте srand(time(NULL)); в начало main.
Иногда повтор как раз полезен — при отладке. Тогда пишут srand(42); с постоянным числом: последовательность будет одинаковой при каждом запуске на этом компьютере, и ошибку легко воспроизвести.
Числа повторяются внутри программы
srand вызывают один раз, в начале программы. Если вызвать srand(time(NULL)) перед каждым rand() (например, в цикле или в своей функции «дай случайное число»), все вызовы за одну секунду получат одно и то же начальное значение — и одно и то же число.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int random_in(int a, int b) {
return rand() % (b - a + 1) + a;
}
int main(void) {
srand(time(NULL));
for (int i = 0; i < 5; i++) {
printf("%d ", random_in(1, 10));
}
printf("\n");
return 0;
}Здесь srand стоит в main один раз, а функция random_in только вызывает rand.
Случайное дробное число
rand() даёт только целые. Дробное от 0 до 1 получается делением на RAND_MAX:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
double r = (double)rand() / RAND_MAX;
double t = 15.0 + r * (25.0 - 15.0);
printf("От 0 до 1: %.3f\n", r);
printf("Температура от 15 до 25: %.1f\n", t);
return 0;
}Приведение (double) обязательно: без него rand() / RAND_MAX — деление целых, и почти всегда получится 0.
Ограничения rand
- В Windows
RAND_MAXравен 32767, поэтомуrand() % 1000000никогда не даст числа больше 32767. Если нужен большой диапазон, аRAND_MAXравен 32767, склеивают два вызова:rand() * 32768 + rand()даёт числа от 0 до 1 073 741 823. В Linux этого не нужно: тамrand()и так доходит до 2 147 483 647. - Остаток
% nделает маленькие числа чуть вероятнее больших, еслиRAND_MAX + 1не делится наn. Для игр и учебных задач это неважно. randне годится для паролей, ключей и всего, что связано с безопасностью: его последовательность можно предсказать. Для таких задач нужны средства операционной системы.