реквотов я использовал синусную функцию, т.е. если число выпавшее в генераторе случ. чисел являеться
корнем синусной функции - то, реквот.
Что-то ты намудрил тут, MaStak. У тебя получается, во-первых, что если в функции Requote() функция MathRand() генерит нуль, то реквоты нет. Но вероятность генерации нуля очень маленькая (1/32768), т.е. почти нулевая. Это условие выполняется крайне редко, т.е. его можно и не учитывать при твоей логике.
Во всех остальных случаях реквота генерится, только если |sin(0.01*Percent*Pi*RND)| < 0.01. Почему Percent внутри функции синуса? Значение Percent при большом количестве попыток влияет на частоту реквот не так, как ты хотел. При Percent = 100 у тебя будет совсем не 100% реквот. Если ты хочешь, чтобы реквота генерилась с частотой Percent, не надо мудрить, и проще всю функцию Requote() заменить вот такой:
bool Requote( double Percent ) { if( MathRand() < Percent * 32.768 - 1 ) return( true ); else return( false ); }
Кстати, в CodeBase есть статья с готовым алгоритмом тестирования реквот, опубликованная больше двух лет назад. Смотри здесь.
Привет, Mathemat. Спасибо, что заглянул.
Попробую представить идею на картинках. Percent задаёт период/частоту выборки(?).
Допустим ГСЧ выбрасывает числа из диапазона 1-100, 0 игнорируем.
Тогда, при Percent=1, функция примет вид
Т.е. Requote=true, если выпадет 100.
Если Percent=3, то Requote=true если выпадет 33 или 66 или 100.
Если Percent=10, то реквот выпадет на числах 10,20,30,40,50,60,70,80,90,100.
Если Percent=100, то частота функции возрастёт на столько что она пройдёт через все числа диапазона.
Ты в своей функции задаёшь диапазон, а я конкретные числа равномерно распределённые по всему диапазону.
Я думал так будет лучше/справедливей.
Горе от ума)
bool fRandomEvent(double aProbability=0.5){ double tRnd=MathRand(); tRnd/=32768; return(tRnd<aProbability); }
MaStak, я твой замысел понял, хотя и не сразу. Давай посмотрим несколько частных случаев.
Скажем, при Percent = 100 для реквоты нужно, чтобы |sin(Pi*RND)| < 0.01. Фактически так оно и будет, т.к. RND - целое число всегда. Все получается.
А если Percent = 60? Тогда условие реквоты - это |sin(0.6*Pi*RND)| < 0.01. Грубо говоря, если 3/5*RND - целое. Это означает, что RND обязано делиться на 5 и никак иначе. Получается, что это только пятая часть от всех чисел, а не 3/5, как ты хотел. Я, правда, не учел тонкого эффекта, связанного с тем, что 3/5*RND должно быть почти целым (у тебя ж не в точности нуль синуса должен быть, а отличие от него на небольшую величину не более 0.01). Но он именно тут не играет роли. Теперь - гораздо более сложный пример. Следи за моими руками и не расслабляйся.
Если Percent = 33, аналогично выходит, что 33/100*RND должно быть почти целым. Если бы мы не учитывали тонкий эффект, то получилось бы, что RND должно делиться на 100, т.е. реквот вроде бы только один процент. С учетом эффекта получится значительно больше. Почему? Если RND = 500, то это явная реквота. Но она останется реквотой и при RND = 497, т.к. 33/100*497 = 33/100*(500-3) = 165 - 99/100 = 164+1/100. Подставляем в функцию синуса, умножая на Pi, и получаем: sin((164+1/100)*Pi) = sin(Pi/100) < 0.01!
Та же фигня будет получаться при всех числах вида 100*N+3, т.к. 33/100*(100*N+3) = целое + 99/100 = другое целое - 1/100. Синус такого аргумента, умноженного на Pi, тоже по модулю меньше 0.01.
Получилось, что реквоты будут при всех вида RND =100N, 100*N +- 3. Это примерно 3 процента. Других случаев реквот вроде бы нет. Но вышло все-таки гораздо меньше, чем ты хотел.
Короче, при твоем алгоритме ты наступаешь на территорию высшей арифметики, которая совсем не такая "непрерывная", как кажется. Надеюсь, объяснил доступно.
P.S. Я лажанулся именно для случая Percent=33 (арифметические ошибки у меня). Там реквот действительно только 1 процент. Но рассуждения, аналогичные зачеркнутым, были бы верны, если бы Percent был равен, скажем, 33.3. Там вообще легко было бы запутаться, т.к. пришлось бы решать несколько уравнений в целых числах.
Еще одна:
double fRandomValue(double aK=0.7){ double tValue=MathRand(); return(MathExp(-MathPow((tValue/32767.0-0.5)*8.0*MathArctan(1)*aK,2))); }
На пике значение 1.
Mathemat, давай тогда смотреть на знаки :)
bool xRequote(double Percent){ bool ret=false; double RND=MathRand(); if(RND<1)return(ret); double y1=MathSin(327.68*Percent*Pi*RND/32768.0); double y2=MathSin(327.68*Percent*Pi*(RND+1)/32768.0); if((y1>0 && y2<0) || (y1<0 && y2>0))ret=true; return(ret);}
Проверил, работает на всех кроме 100%.
Я ещё както пропустил, можно же проверять делиться ли нацело RND на шаг
bool sRequote(double Percent){ bool ret=false; double Step=32768/(Percent*327.68); double RND=MathRand(); if(MathMod(RND,Step)==0)ret=true; return(ret);}
Но при таком варианте работает только до 50%, дальше 1>Step<2. Округления наверно не хватает.
Попробую ещё 2 функцию Integer`a понять.
Вот статейка есть - http://www.nuru.ru/teorver/025.htm. У меня примерно то что в ней, только коэффиценты подобрал, так чтобы было приятно глазу и пик был на единице.
MasTak, я попытался проанализировать твои функции теоретически и выявил некоторые подводные камни. Наверно, проще было бы сделать это практически - просто взять и проверить. Но в любом случае и функции Integer'a, и моя собственная гораздо прозрачнее, чем твои синусоидальные.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Написал простенькую функцию для имитации реквотов.
Суть в следующем, в параметре передаём функции процент вероятности реквота, а
она подбрасывает монетку и сообщает был реквот или нет. Для равномерного распределения вероятностей
реквотов я использовал синусную функцию, т.е. если число выпавшее в генераторе случ. чисел являеться
корнем синусной функции - то, реквот. Странное дело, до 50% работает нормально, а выше процент реквотов
снижаеться :( Почему ? Скрипт ниже