Features of the mql5 language, subtleties and tricks - page 135

 
Vict:

You are very considerate, thank you. I made a mistake, I didn't put brackets, so I would have used the "unfair" function.

ZS: made corrections to the original post.

Please explain why this construction is better than a trivial rand()%max.

ZS: I see what you mean.
Well then - what if max>32767? Your function is of type uint, but generates the same maximum as rand(), i.e. 32767

You'd better use something like

ulong RandULong(ulong max=ULONG_MAX) {return(((ulong)rand()<<60)|((ulong)rand()<<45)|((ulong)rand()<<30)|((ulong)rand()<<15)|(ulong)rand())%max;}
 
Vict:

You are very considerate, thank you. I made a mistake, didn't put brackets, so I would use "unfair" function.

ZS: made corrections to the original post.

Do you realize that if someone wants to use your honest function and write get_rand(10), it will work 3276 times slower than rand()%10

 
Nikolai Semko:

Well then - what if max>32767? After all, your function is of type uint, but generates maximum that rand(), i.e. 32767.

you'd better use something like

And MathRand() returns int, what if someone expects a number with six zeroes from it? Counting on some level of public. Here, you yourself know how to get > 32767.

They just often write rand()%3 without thinking twice and then see my message and realize that it will shift the probabilities.

Do you realize that if someone wants to use your honest function and write get_rand(10), it will work 3276 times slower than rand()%10

Well yes, very slow, for a cycle of a million calls a callback while will happen about 300 times. If your programs consist of bare for() where get_rand() is fidgeting, that would be critical, I guess.

And do you realise that the os scheduler is taking up a lot of CPU time and slowing down execution disproportionately to rand()? If you are in such a hurry, you need some kind of dos.

 
Vict:

And MathRand() returns int, what if someone expects a number with six zeros from it? I'm counting on a certain level of public. Here, you yourself know how to get > 32767.

They just often write rand()%3 without thinking twice and then see my message and realize there will be a probability shift.

Well yes, very slow, for a cycle of a million calls a callback while will happen about 300 times. If your programs consist of bare for() where get_rand() is fidgeting, that would be critical, I guess.

And do you realise that the os scheduler is taking up a lot of CPU time and slowing down execution disproportionately to rand()? If you're in such a hurry, you need some kind of dos.

The speed of functions is critical in optimisation. And it's not about the scheduler and DOS.
 
Vict:

And MathRand() returns int, what if someone expects a number with six zeros from it? I'm counting on a certain level of public. Here, you yourself know how to get > 32767.

They just often write rand()%3 without thinking and see my message and realize that it will shift probabilities.

Well yes, very slow, for a cycle of a million calls a callback while will happen about 300 times. If your programs consist of bare for() where get_rand() is fidgeting, that would be critical, I guess.

And do you realise that the os scheduler is taking up a lot of CPU time and slowing down execution disproportionately to rand()? If you are in such a hurry, you need some kind of dos.

Don't be afraid to admit your mistakes, there's nothing scary or humiliating about it. We all make mistakes. It's normal.
It's much easier and more useful in terms of community perception to say, "Yes, I was wrong. Thank you." instead of trying to make excuses.

This works much faster and more universally:

ulong randUlong(ulong max=ULONG_MAX)
  {
   static bool f=true;
   if(f) {f=false; srand(GetTickCount());}
   return(((ulong)rand()<<60)|((ulong)rand()<<45)|((ulong)rand()<<30)|((ulong)rand()<<15)|(ulong)rand())%max;
  }

You may speed it up if you recode it from ulong to uint, if you don't need big numbers (you need 3 rand() instead of five).

 
Nikolai Semko:

Don't be afraid to admit your mistakes - there's nothing scary and humiliating about it. We all make mistakes. It's okay.
It's easier and more helpful to the community to say, "Yeah, I was wrong. Thank you." Instead of trying to justify yourself.

After all, this option works much faster and more universally:

It can also be speeded up by recoding from ulong to uint, if you don't need big numbers (3 rand() instead of five).

So you are not confused by unfairness of your implementation (in terms of speed, by the way, it will be much slower)? Suit yourself.

Zy: dishonesty - generating different range numbers with different probabilities.
 
Vict:

So you are not confused by the unfairness of your implementation (it will be much slower in terms of speed, by the way)? Suit yourself.

Zy: dishonesty is generating different range numbers with different probability.
Are you serious?
 
Why do people say there is modulo bias when using a random number generator?
Why do people say there is modulo bias when using a random number generator?
  • 2012.06.11
  • user1413793user1413793 5,32651933
  • stackoverflow.com
I have seen this question asked a lot but never seen a true concrete answer to it. So I am going to post one here which will hopefully help people understand why exactly there is "modulo bias" when using a random number generator, like in C++.
 
So you're willing to set fire to a $100 note to find a dime rolled under the bed?
 
Nikolai Semko:
So you're willing to set fire to a $100 note to find a dime rolled under the bed?

You should not underestimate the role of probabilities. At multimillion iterations these "rolled pennies" will cost you quite tangible figures. Moreover, your code is obviously irrational at small ranges (constantly making five calls to rand() is exactly the "burning the note")

Six months ago this topic was already discussed on the forum, I suggested this option:

Forum on trading, automated trading systems and testing trading strategies

How to get a random number in N-depth range ?

Alexey Navoykov, 2018.12.31 01:25

My last code turned out to be incorrect. I made too much trouble with digits. Here is right variant and more concise at the same time:

ulong RandomLong(ulong range)
{
 #define _MAXRND(range, rnd_range)  ((rnd_range) - ((rnd_range)-range)%range - 1) 
 #define _RND (ulong)rand()
  ulong rnd, max, const bit=1;
  if (range <= bit<<15) { if (!range) return0;  max=_MAXRND(range, 1<<15);  while((rnd=_RND) > max);  return rnd%range; }
  if (range <= bit<<30) { max=_MAXRND(range, bit<<30);  while((rnd=(_RND | _RND<<15)) > max);  return rnd%range; }
  if (range <= bit<<45) { max=_MAXRND(range, bit<<45);  while((rnd=(_RND | _RND<<15 | _RND<<30)) > max);  return rnd%range;  }
  if (range <= bit<<60) { max=_MAXRND(range, bit<<60);  while((rnd=(_RND | _RND<<15 | _RND<<30 | _RND<<45)) > max);  return rnd%range; }
                  else  { max=_MAXRND(range, bit<<64);  while((rnd=(_RND | _RND<<15 | _RND<<30 | _RND<<45 | _RND<<60)) > max);  return rnd%range; }
 #undef _RND               
 #undef _MAXRND
}
Reason: