Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - VBA

Страница: 1 | 2 |

 

  Вопрос: генерация случайных чисел Добавлено: 20.08.07 14:57  

Автор вопроса:  APS | ICQ: 234458121 
Есть лист со списком вопросов, которые располагаются со 2 по 11 строки. Из них нужно выбрать случайным образом 5 неповторяющихся вопросов.


  For i = 1 To 5
        f = Int((10 * Rnd(1)) + 2)
        y = y + 1
        ReDim Preserve vl(y)
        vl(y - 1) = Worksheets(1).Cells(f, 1).Value
    Next


Но данный код допускает повторения. Как сделать, чтобы случанйые числа не повторялись?

Ответить

  Ответы Всего ответов: 25  

Номер ответа: 1
Автор ответа:
 shuffle



Администратор

ICQ: 201502381 

Вопросов: 15
Ответов: 737
 Профиль | | #1 Добавлено: 20.08.07 15:27
Сохраняй в массив все числа, которое уже были сгенерины, и при следующей итерации генери новое число до тех пор, пока оно будет попадаться в этом массиве.

Ответить

Номер ответа: 2
Автор ответа:
 APS



ICQ: 234458121 

Вопросов: 38
Ответов: 107
 Профиль | | #2 Добавлено: 20.08.07 23:30
Этот вариант понятен, но при небольшой выборке, может врубить циклу. И реализация его не очень интересна.
Как мне кажется, ответ лежит где-то на поверхности, и можно обойтись одним-двумя операторами. Только вот как, пока не могу дойти.

Ответить

Номер ответа: 3
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #3
Добавлено: 21.08.07 06:02
Сохраняй сгенеренные числа в массив и на каждой итерации бери верхним пределом число, на единицу меньшее предыдущего. Отсчитывай по этому массиву номер числа, из тех, которых еще не было.

Ответить

Номер ответа: 4
Автор ответа:
 Egor



Вопросов: 2
Ответов: 5
 Профиль | | #4 Добавлено: 06.10.07 10:41
Можеш показать это в коде?

Ответить

Номер ответа: 5
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #5
Добавлено: 06.10.07 15:12
Самый простой вариант: бери рандомом число, меняй его местами с последним и на следующей итерации бери случайное число из куска, на единицу меньшего

vector<int> getrnd(vector<int> a, int n){
vector<int> res;
for(int i = 0; i < n; i++){
int t = random(0, n-i);
res.push(a[i];);
swap(a[i], a[n-i];);
}
}

Ответить

Номер ответа: 6
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #6
Добавлено: 06.10.07 15:13
Патч:
res.push_back(a[t];);
swap(a[t], a[n-i];);

Ответить

Номер ответа: 7
Автор ответа:
 HACKER


 

Разработчик Offline Client

Вопросов: 236
Ответов: 8362
 Профиль | | #7 Добавлено: 06.10.07 16:09
Помойму в std что-то готовое было для генерации неповторяемой последовательности чисел. Хотя я могу ошибаться.

Ответить

Номер ответа: 8
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #8
Добавлено: 07.10.07 09:36
Ну да, например, random_shuffle. Но это 1) жрет больше ресурсов; 2) не передает алгоритм

Ответить

Номер ответа: 9
Автор ответа:
 Pavel



Вопросов: 0
Ответов: 82
 Профиль | | #9 Добавлено: 07.10.07 14:53
Использовать инструкцию Randomize

Ответить

Номер ответа: 10
Автор ответа:
 ADSemenov.ru



Вопросов: 5
Ответов: 276
 Web-сайт: www.adsemenov.ru
 Профиль | | #10
Добавлено: 07.10.07 16:25
____ Я для случайности в параметры обычных функций генерации случайных чисел ставлю системное время. Это исключает повторение "случайной" последовательности при перезапускке программы, поскольку зависит от времени её запуска.
____ В VBA оператор Randomize как раз и делает эту опреацию для последующего использования в rnd на внутреннем уровне.
  Randomize
  For i = 1 To 5
        f = Int((10 * Rnd(1)) + 2)
        y = y + 1
        ReDim Preserve vl(y)
        vl(y - 1) = Worksheets(1).Cells(f, 1).Value
    Next

____ В операторе есть ещё возможность ставить параметр, тогда инициализация случайности будет точно соответствовать этому параметру, а не системному времени.

Ответить

Номер ответа: 11
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #11
Добавлено: 07.10.07 17:18
Pavel, ADSemenov.ru, на этом форуме принято читать вопрос перед тем, как ответить.

Ответить

Номер ответа: 12
Автор ответа:
 ADSemenov.ru



Вопросов: 5
Ответов: 276
 Web-сайт: www.adsemenov.ru
 Профиль | | #12
Добавлено: 07.10.07 18:30
____ И то верно. Хотя и проблема одинаковости выбора при перезапуске программы тоже бывает важна.

____ Я бы завёл второй массив — индексов (номера строк) выбранных вопросов и во вложенном цикле проверял наличие повтора. Хотя можно и сам текст в v1() сравнивать.

____ Спасибо Sharp'у за науку. :)

Ответить

Номер ответа: 13
Автор ответа:
 ADSemenov.ru



Вопросов: 5
Ответов: 276
 Web-сайт: www.adsemenov.ru
 Профиль | | #13
Добавлено: 07.10.07 18:40
____ Внимательно прочитав вопрос предлагаю такое решение. —

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

Ответить

Номер ответа: 14
Автор ответа:
 GenyaA



Вопросов: 0
Ответов: 185
 Web-сайт: www.genyaa.nm.ru
 Профиль | | #14
Добавлено: 07.10.07 21:12
Вот вариант решения через коллекцию:
Sub nnn()
    Dim cc As New Collection, i As Integer, vl(1 To 5) As String, f As Integer, c As Range
    i = 0
'Формируем коллекцию
    For Each c In Range("A2:A11";).Cells
        cc.Add Item:=c.Cells
    Next c
'выбираем случаный элемент коллекции в массив и удаляем его из коллекции
    For i = 1 To 5
        f = Int(((11 - i) * Rnd(1)) + 1)
        vl(i) = cc(f)
        cc.Remove (f)
        Debug.Print vl(i) 'проверка
    Next i
End Sub

Ответить

Номер ответа: 15
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #15
Добавлено: 08.10.07 13:45
Я бы завёл второй массив — индексов (номера строк) выбранных вопросов и во вложенном цикле проверял наличие повтора. Хотя можно и сам текст в v1() сравнивать.

Это неустойчивый и нелинейный относительно числа выбранных элементов алгоритм. Верный приведен мной. Хуже варианта с коллекциями вообще сложно придумать.

Ответить

Страница: 1 | 2 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам