Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.73
Faltfromoss
0 / 0 / 0
Регистрация: 28.03.2014
Сообщений: 32
#1

Генератор случайных чисел - C++

29.06.2014, 14:10. Просмотров 1434. Ответов 16
Метки нет (Все метки)

Еще одна тема о генераторе. Только вопрос, на который я пока не нашел ответа в других темах. Как сгенерировать случайное число в двух или более разных заданных диапазонах? Т. е. если мы стандартно описываем генерацию в диапазоне от m до n:
C++
1
rand() % (n+1-m) + m
то здесь всё ясно. Но мне нужно сгенерировать например число, которое будет входить в один из диапазанов, например от 1 до 10 или от 23 до 72 или от 123 до 140 и т. д. и т. п. Я пока похожих примеров не нашел. Либо оно никому не нужно кроме меня, либо решение на столько простое, что никто этим вопросом не задавался кроме меня. Либо хреново искал, тоже как вариант.
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Убежденный
Системный программист
Эксперт С++
15102 / 6797 / 1073
Регистрация: 02.05.2013
Сообщений: 11,111
Завершенные тесты: 1
29.06.2014, 14:15     Генератор случайных чисел #2
Сгенерировать один rand и использовать его как диапазон для второго rand.
Kerry_Jr
Модератор
Эксперт PHP
2141 / 1937 / 676
Регистрация: 14.05.2014
Сообщений: 5,681
Записей в блоге: 1
Завершенные тесты: 5
29.06.2014, 14:17     Генератор случайных чисел #3
От m до n
C++
1
rand() % (n - m + 1) + m
А в чем проблема-то?
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
29.06.2014, 14:23     Генератор случайных чисел #4
Цитата Сообщение от Faltfromoss Посмотреть сообщение
либо решение на столько простое..
C++
1
2
3
4
5
std::random_device rd;
std::uniform_int_distribution<int> spread1 (23,72); // между 23 и 72
std::uniform_int_distribution<int> spread2 (123,140); // между 123 и 140
int rdnum1 = spread1(rd);
int rdnum2 = spread2(rd)
Faltfromoss
0 / 0 / 0
Регистрация: 28.03.2014
Сообщений: 32
29.06.2014, 14:24  [ТС]     Генератор случайных чисел #5
Цитата Сообщение от Kerry_Jr Посмотреть сообщение
А в чем проблема-то?
Проблема в том, что в этот код я могу подставить границы одного, диапазона, например m=5, n=15 и rand() будет возвращать числа от 5 до 15 и всё. А мне нужно, к примеру, чтобы помимо этого диапазона от 5 до 15-ти он возвращал числа еще из другого диапазона, к примеру от 23 до 42 тоже случайным образом

Цитата Сообщение от Убежденный Посмотреть сообщение
Сгенерировать один rand и использовать его как диапазон для второго rand.
Немного не понял ход мысли. :\
SlavaSSU
215 / 160 / 45
Регистрация: 17.07.2012
Сообщений: 587
29.06.2014, 14:26     Генератор случайных чисел #6
Faltfromoss, как варик, сгенерить первый ранд из 1 диапазона, сгенерить 2 ранд из 2 диапазона, а потом рандомно выбать один из них xD
Faltfromoss
0 / 0 / 0
Регистрация: 28.03.2014
Сообщений: 32
29.06.2014, 14:28  [ТС]     Генератор случайных чисел #7
Цитата Сообщение от SlavaSSU Посмотреть сообщение
Faltfromoss, как варик, сгенерить первый ранд из 1 диапазона, сгенерить 2 ранд из 2 диапазона, а потом рандомно выбать один из них xD
Я сейчас больше к этому варианту и склоняюсь, других пока не вижу.
astronomydomine
0 / 0 / 0
Регистрация: 17.09.2013
Сообщений: 3
29.06.2014, 14:29     Генератор случайных чисел #8
Есть вариант написать цикл, в котором программа генерирует число в диапазоне от минимального до максимального числа из данных диапазонов и каждый раз проверяет, если оно не входит в один из диапазонов, то снова генерирует до тех пор, пока не появится нужное число. Просто это много времени займет.
Kerry_Jr
Модератор
Эксперт PHP
2141 / 1937 / 676
Регистрация: 14.05.2014
Сообщений: 5,681
Записей в блоге: 1
Завершенные тесты: 5
29.06.2014, 14:37     Генератор случайных чисел #9
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <ctime>
#include <cstdlib>
 
int main()
{
    setlocale(LC_ALL, "");
    int n;
    srand(unsigned(time(NULL)));
    // Предположим, имеется три диапазона,
    // в один из которых должно входить число
    // берем минимальное и максимальное из всех диапазонов
    // и находим случайное, затем проверяем, входит ли оно
    // в один из диапазонов, если да - возвращаем, нет - проделываем это снова
    // Диапазоны 1-10, 23-79, 110-140
    while (true)
    {
        n = rand() % (140 -1 + 1) + 1;
        if ((n > 0 && n < 11) || (n > 22 && n < 80) || (n > 109 && n < 141)) break;
    }
    std::cout << n << std::endl;
    return 0;
}
Долго работает

Добавлено через 55 секунд
astronomydomine, такая же идея пришла в голову
Faltfromoss
0 / 0 / 0
Регистрация: 28.03.2014
Сообщений: 32
29.06.2014, 14:40  [ТС]     Генератор случайных чисел #10
Kerry_Jr, согласен, как вариант тоже вполне применимый.
0x10
2456 / 1628 / 238
Регистрация: 24.11.2012
Сообщений: 4,003
29.06.2014, 14:42     Генератор случайных чисел #11
Сообщение было отмечено автором темы, экспертом или модератором как ответ
astronomydomine, Kerry_Jr, жесть какая... Надеюсь, сами понимаете, что такие решения неприемлемы.

Добавлено через 2 минуты
Faltfromoss,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <map>
#include <vector>
 
int main() {
    std::vector<std::pair<int, int>> ranges {
        {0, 10},
        {20, 25},
        {50, 60}
    };
    
    std::map<int, int> counters;
    
    for (int i = 0; i < 100000; ++i) {
        const int range_index = rand() % ranges.size();
        const auto& range = ranges[range_index];
        const int number = rand() % (range.second - range.first + 1) + range.first;
        ++counters[number];
    }
    
    for (const auto& item : counters) {
        std::cout << item.first << ": " << item.second << std::endl;
    }
    
    return 0;
}
http://ideone.com/3zvfgI
ValeryS
Модератор
6511 / 4977 / 460
Регистрация: 14.02.2011
Сообщений: 16,485
29.06.2014, 14:45     Генератор случайных чисел #12
хоть сто диапазонов
вот с таким подходом
C++
1
2
3
4
5
6
7
8
9
10
11
int m=rand()%2;
switch(m)
{
  case 0:
    n=rand()%(k0+1-p0)+p0;
    break;
  case 1:
    n=rand()%(k1+1-p1)+p1;
    break;
 
}
Убежденный
Системный программист
Эксперт С++
15102 / 6797 / 1073
Регистрация: 02.05.2013
Сообщений: 11,111
Завершенные тесты: 1
29.06.2014, 14:47     Генератор случайных чисел #13
Цитата Сообщение от Faltfromoss Посмотреть сообщение
Немного не понял ход мысли. :\
Пусть есть N диапазонов, у каждого свои min- и max-значения.
Генерируем первое случайное число от 1 до N - это будет номер диапазона.
А затем второе случайное число от min до max внутри выбранного диапазона.

0x10 расписал уже все выше, добавить нечего.
zss
Модератор
Эксперт С++
6248 / 5851 / 1891
Регистрация: 18.12.2011
Сообщений: 14,986
Завершенные тесты: 1
29.06.2014, 14:50     Генератор случайных чисел #14
Тогда еще вариант
C++
1
2
3
4
5
6
7
8
9
10
11
12
// Предположим, имеется три диапазона,
    // в один из которых должно входить число
    // берем сумму интервалов всех диапазонов
    // и находим случайное, затем проверяем, переходит ли оно границу,
    // если да - прибавляем пропускаемый интервал
    // Диапазоны 1-10, 23-79, 110-140
    // сумма интервалов 9+56+30=95
    n = rand() %95+1;
    if(n>10)
         n+=13;
    if(n>79)
         n+=31;
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
29.06.2014, 14:50     Генератор случайных чисел #15
как варик, сгенерить первый ранд из 1 диапазона, сгенерить 2 ранд из 2 диапазона, а потом рандомно выбать один из них
Есть вариант написать цикл, в котором программа генерирует число в диапазоне от минимального до максимального числа из данных диапазонов и каждый раз проверяет...
работать оно конечно будет, но нехорошо так делать совсем(с)

пишем функцию вычисления длинны диапазона, находим суммарную длину всех диапазонов, бросаем кость по суммарной длине, вычисляем в какой диапазон и элемент попали. Такой способ будет работать во первых быстро, во вторых не будет нарушать тип распределения.
aleks_tar
2 / 2 / 0
Регистрация: 19.06.2014
Сообщений: 17
29.06.2014, 15:26     Генератор случайных чисел #16
Для диапазона используется класс Range со свойствами first_ и last_ (первый и последний), создаётся вектор, в который заносится необходимое количество элементов типа Range. Для генерации случайного числа вызывается функция getRandomInSeveralRanges(). В этой функции сначала случайным образом выбирается один из диапазонов, дальше в этом диапазоне случайным образом выбирается число. Данный пример работает только с целыми числами, но его, при желании, можно доработать, чтобы он работал, например, с числами с плавающей точкой.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <cstdlib>
#include <vector>
#include <ctime>
#include <iostream>
 
class Range
{
    size_t first_;
    size_t last_;
public:
    Range(const size_t first, const size_t last)
    {
        first_ = first;
        last_ = last;
    }
    
    size_t getFirst() const
    {
        return first_;
    }
    
    size_t getLast() const
    {
        return last_;
    }
};
 
int getRandomInSeveralRanges(const std::vector<Range> ranges)
{
    size_t number_of_ranges = rand() % ranges.size();
    return rand() % (ranges.at(number_of_ranges).getLast() - 
        ranges.at(number_of_ranges).getFirst()) + 
        ranges.at(number_of_ranges).getFirst();
}
 
int main()
{
    // пример использования функции getRandomInSeveralRanges())
    std::vector<Range> ranges;
    ranges.push_back(Range(10, 20));
    ranges.push_back(Range(30, 40));
    // srand() нужно вызвать перед вызовом функции getRandomInSeveralRanges(),
    // но только один раз не зависимо от того, сколько раз после этого будет
    // вызвана эта функция 
    srand(time(NULL));
    for(int i = 0 ; i < 40; ++i)
    {
        std::cout << getRandomInSeveralRanges(ranges) << std::endl;
    }
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.06.2014, 15:43     Генератор случайных чисел
Еще ссылки по теме:

C++ генератор случайных чисел
C++ Генератор случайных чисел
C++ Генератор случайных чисел
C++ Генератор случайных чисел

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
29.06.2014, 15:43     Генератор случайных чисел #17
aleks_tar, пусть диапазоны {1,2} и {5, 10000000},
вопрос:
1.) во сколько раз 1 будет выпадать чаще 5 ?
2.) так должно быть?
Yandex
Объявления
29.06.2014, 15:43     Генератор случайных чисел
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru