Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Добавил для сравнения в свой скрипт MathRandomUniform
Задаю генерацию точек до 1000000. Для оценки распределения вывожу все 1000000 точек на экран в виде квадрата 1000*1000. Чем больше попаданий ГСЧ в точку, тем ярче ее цвет.
Задал 10 млн повторений ГСЧ, в среднем в каждую точку должно попасть 10 раз.
Вот результаты:
RND:
Мой вариант RandomInteger:
На MathRand():
На MathRandomUniform():
Первые два ГСЧ вполне равномерные, 3 и 4 с пропусками, т.е. неравномерные.
Пропуски обусловлены разрешением MathRand = 32767. При множителе 1000000 получим пропуски 1000000/32767=30 точек. MathRandomUniform по картинке похожа, видимо те же пропуски в 30 единиц.
Другой вариант. Зададим максимальное число 30000. RND и RandomInteger равномерны, как при миллионе. MathRand и MathRandomUniform выглядит так (с увеличенным куском):
Пропусков (черных точек до позиции 30000) нет. Но часть заметно ярче. Это неравномерность округления 30000/32767. Каждая 11-я точка получает вдвое больше попаданий.
Что-то равномерное можно получить от MathRand при максимуме до 3000... 4000. Вот увеличенный вариант для 3500:
Первые два варианта при приближении максимального числа к 100 миллионам для RandomInteger (у которой разрешение около 1 миллиарда) и 400 млн. при разрешении 4 млрд. для RND, - тоже начнут неравномерно распределяться за счет округления.
Файл приложил, можете повторить эксперимент.
Для себя решил пользоваться своей функцией, она медленнее на 25% чем RND, но компактнее и понятнее, можно увеличить разрешение еще в 32767 раз, см. код в блоге.
Примечание:
Разработчик RND из статьи указал, что
При каждом перезапуске, ставлю seed=0, но картинка с распределениями при перезапусках не меняется. Т.е. утверждение неверное. По коду тоже не видно почему оно должно стать случайным. Т.о. для случайной инициализации надо seed устанавливать в случайное число, например seed=GetTickCount();
Для функции RandomInteger() при перезапусках видно перераспределение точек. Если установить srand(0); то при перезапусках распределение тоже начинает повторяться. Т.е. для этой функции для случайной инициализации надо либо не вызывать srand, либо тоже с меткой врмени MathSrand(GetTickCount()).
Учтите, что xor128 проходит специальные тесты на случайность, а со стандартным rand может быть такое
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Машинное обучение в трейдинге: теория, практика, торговля и не только
Rorschach, 2020.04.19 22:18
Я рукожоп, ГСЧ сломал(((
1 способ: w должно быть степенью 2, k кратно 4
2 способ: раскоментировать srand
2 способ должен сработать так же на Вихре МерсенаУчтите, что xor128 проходит специальные тесты на случайность, а со стандартным rand может быть такое
Вы отображаете каждый 16-й вызов rand. Какая то закономерность из этой периодичности проявляется.
У меня используется все подряд вызовы по 2 в каждом. Визуально, по моим картинкам не вижу разницы с xor128 для 10 млн повторений.
Учтите, что xor128 проходит специальные тесты на случайность, а со стандартным rand может быть такое
Попробовал в вашу функцию подставить свою и xor128
void OnStart()
{CCanvas C;
RND rn; rn.SRand(0);
int h=1024;
int w=2048;
C.CreateBitmapLabel("11",100,100,w,h);
for(int y=0;y<h;y++)
{//srand(GetMicrosecondCount());
rn.SRand(GetMicrosecondCount());
for(int x=0;x<w;x++)
{uchar c=0;
for(int k=0;k<16;k++)
//{c=uchar(255.*rand()/32767.);}
//{c=uchar(255.*RandomInteger(1073741824)/1073741824.0); }
{c=(uchar)(255.0*rn.Rand_01()); }
C.PixelSet(x,y,ARGB(255,c,c,c));
}
}
C.Update();
}
int RandomInteger(int max_vl){return (int)MathFloor((MathRand()+MathRand()*32767.0)/1073741824.0*max_vl);}//случайное Int от 0 до 1073741824
//если из define переместить в код RNDUint, то скорость работы увеличится на 30% для 10 млн повторов с 600 мс до 850 мс. Это почти как RandomInteger()
#define xor32 xx=xx^(xx<<13);xx=xx^(xx>>17);xx=xx^(xx<<5)
#define xor128 t=(x^(x<<11));x=y;y=z;z=w;w=(w^(w>>19))^(t^(t>>8))
#define inidat x=123456789;y=362436069;z=521288629;w=88675123;xx=2463534242
class RND{
protected:
uint x,y,z,w,xx,t;
public:
RND(void){inidat;};
~RND(void){};
uint RandMaxUI(uint max_v) {xor128;return((uint)MathFloor((double)w/UINT_MAX*max_v));};//равномерное распределение на отрезке [0,max_v]. uint
int RandMaxI(int max_v) {xor128;return((int) MathFloor((double)w/UINT_MAX*max_v));};//равномерное распределение на отрезке [0,max_v]. int
uint Rand() {xor128;return(w);};//равномерное распределение на отрезке [0,UINT_MAX=4294967295].
double Rand_01() {xor128;return((double)w/UINT_MAX);};//равномерное распределение на отрезке [0,1].
void Reset() {inidat;};//сброс всех исходных значений в первоначальное состояние.
void SRand(uint seed) {//установка новых исходных значений генератора.seed= [0,UINT_MAX=4294967295]. При seed=0 функция меняет начальные значения случайным образом.
int i;if(seed!=0){xx=seed;}for(i=0;i<16;i++){xor32;}xor32;x=xx;xor32;y=xx;xor32;z=xx;xor32;w=xx;for(i=0;i<16;i++){xor128;}
};
};
C RandomInteger() какие то разводы тоже есть.
С xor128 получше, но есть какая-то полоса:
А вообще не уверен, что при обычном использовании, (а не 1 из 16) эти разводы из RandomInteger() как то повлияют... Да и не понятно, что они означают...
Но пожалуй xor128 все же надежнее использовать.
Учтите, что xor128 проходит специальные тесты на случайность, а со стандартным rand может быть такое
А у вас есть код Мерсена? У меня где-то был на OpenCL, руки не дошли перенести на MQL5. Интересно было бы сравнить.
А у вас есть код Мерсена? У меня где-то был на OpenCL, руки не дошли перенести на MQL5. Интересно было бы сравнить.
Здесь, сам не пользовался.
Вы отображаете каждый 16-й вызов rand. Какая то закономерность из этой периодичности проявляется.
У меня используется все подряд вызовы по 2 в каждом. Визуально, по моим картинкам не вижу разницы с xor128 для 10 млн повторений.
Я не знаю какая у вас цель использования, просто предупреждаю, что могут быть сюрпризы.
Здесь, сам не пользовался.
Спасибо! Код оказался больше, чем на OpenCL. Как нибудь постараюсь разобраться.
дружный попадос в тер.вер., магию целых чисел, округления, модульную арифметику и фокусы double :-)
если f(x) :: integer равномерно распределённое (0;N] то это отнюдь не значит что g(x)=N/(double)f(x) будет равномерно распределено на (0;1] и к тому-же пройдёт все тесты.
примерно то же самое про g(x) = f(x) mod M , за редким исключением N mod M = 0.
PS/ кстати и g(x)=f(x)/(double)N тоже не будет равномерной. Там будут фокусы деления. То есть на графиках будет проявляться муар.
PPS/ для визуального "теста" на рандомность,кроме тупого квадрата по модулю, применяются вариации "улитки улама"
Здесь, сам не пользовался.
Замерил производительность CRandomMersenne и CRandomMother из этого кода. Они в 3 раза медленнее xor128. Это не очень радует. Но по вашему коду, где вы сломали ГСЧ, они выглядят лучше, чем xor128 (без вертикальной полоски).