|
Болтовня Разговоры на любые темы (думайте, о чем пишите) |
11.10.2005, 21:17
|
#1
|
Дэвелопер
Регистрация: 07.09.2005
Сообщений: 1,519
Написано 66 полезных сообщений (для 164 пользователей)
|
Забавная задачка:
Используя генератор Rnd, написать ф-ю, которая возвращала бы значения 1, 2 или 3 с равной вероятностью.
Код для подсчета вероятностей можно использовать вроде этого:
Dim Value(4)
For q=0 To 10000
X=Rnd(3)
Value(X)=Value(X)+1
Next
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
End
P.S. Я не свихнулся, попробуйте сами.
|
(Offline)
|
|
11.10.2005, 22:09
|
#2
|
Администратор
Регистрация: 03.09.2005
Сообщений: 2,408
Написано 301 полезных сообщений (для 996 пользователей)
|
хммм, ну вероятность ты подсчитал, а где сама функция генерации самого числа по подсчитанным результатам?...
есть кривая (не помню какого ученого) показывающая, что числа в середине промежутка выпадают чаще, чем по краям, это уже давно всем известно...
__________________
Как минимум я помог многим (с)
|
(Offline)
|
|
12.10.2005, 00:06
|
#3
|
Дэвелопер
Регистрация: 07.09.2005
Сообщений: 1,519
Написано 66 полезных сообщений (для 164 пользователей)
|
хммм, ну вероятность ты подсчитал, а где сама функция генерации самого числа по подсчитанным результатам?...
|
В выводе формулы и заключалась задачка.
Формулу надо бы по идее вписать вместо "Rnd(3)"
числа в середине промежутка выпадают чаще, чем по краям, это уже давно всем известно...
|
Вот заче-е-ем было это говори-и-ить? Вот всю интригу испо-о-ортил! :'((
Ладно, раз номер не прошел, тогда так:
Создать, на основе Rnd() ф-ю, которая возвращала бы 1,2 или 3 с близкой вероятностью.
P.S. Сядьте и потестите варианты; не зря ведь говорю, не просто прикалываюсь: последовательности вероятностей можно получить очень интригующие.
|
(Offline)
|
|
12.10.2005, 00:26
|
#4
|
Администратор
Регистрация: 03.09.2005
Сообщений: 2,408
Написано 301 полезных сообщений (для 996 пользователей)
|
ну, я бы увеличил бы границы допустим в 10 раз (чем больше, тем мы больше растянем график, и сделаем его плавней), и пустил бы цикл, пока результат бы не попадал в нужные пределы... типа:
Dim Value(4)
For q=0 To 10000
X=aRnd(1,4)
Value(X)=Value(X)+1
Next
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
End
function arnd%(b%,e%)
b1%=-b%*10
e1%=e%*10
repeat
r%=rnd(b1%,e1%)
until r%>=b% and r%<=e%
return r%
end function
вот, накидал в броузере... хз пойдет или нет... но алгоритм думаю ясен...
в алгоритме есть охренительный недостаток... будет очень медленно работать...
можно еще разорвать этот график и сложить его... порвать посередине и первый после среднего элемента прибавить к первому сначала и т.п... но это только графически, а как это кодом замутить - хз...
__________________
Как минимум я помог многим (с)
|
(Offline)
|
|
12.10.2005, 00:36
|
#5
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ну если использовать счетчики как в первом примере, то можно найти в них наибольщую и наименьшую вероятность и если они отличаются друг от друга больше ну скажем чем на заданную величину (например 5%) то возвращать число которое соответствует наименьшей вероятности, а если разница меньше заданной то использовать оператор Rand()
Больше ничего в голову не лезет
|
(Offline)
|
|
12.10.2005, 00:48
|
#6
|
Администратор
Регистрация: 03.09.2005
Сообщений: 2,408
Написано 301 полезных сообщений (для 996 пользователей)
|
ага, придумал как график рвать:
Dim Value(4)
For q=0 To 10000
X=aRnd(1,4)
Value(X)=Value(X)+1
Next
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
End
function arnd%(b%,e%)
r%=rnd(b%,e%*2)
if r>e then r=r-e
return r%
end function
по скорости работы побыстрей и график гораздо ровнее чем в простом rnd
надо теперь совместить два метода и все.
__________________
Как минимум я помог многим (с)
|
(Offline)
|
|
12.10.2005, 00:54
|
#7
|
Дэвелопер
Регистрация: 07.09.2005
Сообщений: 1,519
Написано 66 полезных сообщений (для 164 пользователей)
|
Вах, хитрые методы! У меня всё намного прозаичнее, даже стыдно становится выкладывать свою идею...
Давайте, еще подожду пару идей- и раскроюсь, если не отгадаете...
А если придумаете лучше- выдам за свою идею!/шутка/ )
P.S. Задачка хоть и прикол, но ИМХО вопрос довольно важен. Многое делается с помощью псевдослучайных чисел Rnd(), и важно, чтоб они были действительно хоть и псевдо-, но случайными...
|
(Offline)
|
|
12.10.2005, 00:54
|
#8
|
Администратор
Регистрация: 03.09.2005
Сообщений: 2,408
Написано 301 полезных сообщений (для 996 пользователей)
|
совместив два метода получил следующий:
Dim Value(4)
For q=0 To 10000
X=aRnd(1,4)
Value(X)=Value(X)+1
Next
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
End
function arnd%(b%,e%)
b1%=-b%*10
e1%=e%*20
repeat
r%=rnd(b1%,e1%)
until r%>=b% and r%<=e%
if r>e then r=r-e
return r%
end function
результат - супер! скорость работы - подбирается коэффициентами умножения... тут типа движок <Скорость> -----0----- <Ровнее график> чемто надо жертвовать..
__________________
Как минимум я помог многим (с)
|
(Offline)
|
|
12.10.2005, 01:04
|
#9
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
А вот что я придумал :
Dim Value(4)
For q=0 To 1000000
X=arnd(1,4)
Value(X)=Value(X)+1
Next
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
End
Function arnd%(b%,e%)
If Rand(0,1) Then
Return Rnd(b%,e%/2)
Else
Return Rnd(e%/2+1,e%)
EndIf
End Function
На большом количестве испытаний показывает почти одинаковые результаты
|
(Offline)
|
|
12.10.2005, 08:41
|
#10
|
ПроЭктировщик
Регистрация: 04.09.2005
Сообщений: 139
Написано одно полезное сообщение
|
последние коды - в ФАК однозначно!
|
(Offline)
|
|
12.10.2005, 13:13
|
#12
|
Дэвелопер
Регистрация: 07.09.2005
Сообщений: 1,519
Написано 66 полезных сообщений (для 164 пользователей)
|
1. Прост до глупости. Работает соответственно.
Dim Value(4)
For q=0 To 100000
X=Rnd(3000)
X=X/1000+1
Value(X)=Value(X)+1
Next
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/1000+"% случаев..."
Next
WaitKey()
2. Работает на основе исправления "глюков" округления
Dim Value(4)
For q=0 To 10000
X=aRnd(2)+1
Value(X)=Value(X)+1
Next
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
Function aRnd(RndValue#)
RndCounter=Rnd(RndValue+1)
If RndCounter=RndValue+1 Then RndCounter=0
Return RndCounter
End Function
Вот такие пироги...
|
(Offline)
|
|
12.10.2005, 22:14
|
#13
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
По моему вообже не надо никаких новых функций, до этого мы еще вчера с SubZer0 додумались, надо просто вызывать функцию Rnd следующим образом:
Rnd(0.5,3.5)
или
Rand(1,3)
и все, а на счет вероятностей появления того или иного числа, то в блитце, по моему, нет никакой кривой и все появляющиеся цифры равновероятны.
Просто в твоем первом примере на числа 1 и 2 отводился промежуток в два раза меньше, чем на 2 (от 1 до 1.5 - для единици, от 1.5 до 2.5 - для двойки и 2.5 до 3 для тройки).
|
(Offline)
|
|
12.10.2005, 23:49
|
#14
|
Администратор
Регистрация: 03.09.2005
Сообщений: 2,408
Написано 301 полезных сообщений (для 996 пользователей)
|
кстати в задаче был маленький подвох, я только сейчас додумался...
попробуйте запустить вот такой код...
seedrnd millisecs()
Dim Value(20)
For q=0 To 10000
X=Rnd(20)
Value(X)=Value(X)+1
Next
For q=0 To 20
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
end
оказывается генератор целых случайных чисел освобожден от этого графика распределения вероятностей. Странно почему он дает кривые значения на малых диапазонах... (не считая крайние значения)
__________________
Как минимум я помог многим (с)
|
(Offline)
|
|
13.10.2005, 00:20
|
#15
|
Дэвелопер
Регистрация: 07.09.2005
Сообщений: 1,519
Написано 66 полезных сообщений (для 164 пользователей)
|
)
Не считая крайних, он и не дает. Но на малом диапазоне эти крайние могут сильно портить нервы, если не юзать "хитрометоды". Зато теперь таких приемов предостаточно: и больше никто не будет ломать голову и ценное оборудование.
Кстати, если генератор случайных, работающий в заданом узком диапазоне, вызывается изредка и асинхронно (к примеру, для выбора фразы-ответа юнита или там анимации падения врага), то проще вообще юзать что то подобное:
Dim Value(4)
While q<10000
RndCounter= RndCounter+1
If RndCounter>3 Then RndCounter=1
If Rnd(10)<2 Then;эта строка иммитирует асинхронные вызовы.
q=q+1
X=RndCounter
Value(X)=Value(X)+1
EndIf
Wend
For q=0 To 4
Print q+" возвращалось приблизительно в "+ Value(q)/100+"% случаев..."
Next
WaitKey()
P.S. Потому я задачку и называл "забавной" и поселил в Болтовню, что в ней мирно уживаются два маленьких подвоха.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 01:31.
|