Unique groups of numbers

 
Say for example I have a range of numbers I can use from 1 - 10 ok.
What I actually want is unique sequences of that range, ie.
10,9,7,8,4,6,5,1,3,2
2,1,4,3,5,6,7,8,9,10

I know you can shuffle arrays but how do get uniques shuffles with maybe a seed number like srand to create

random groups of numbers between 10 and 1?

Thanks in advance

 
bonechair:
Say for example I have a range of numbers I can use from 1 - 10 ok.
What I actually want is unique sequences of that range, ie.
10,9,7,8,4,6,5,1,3,2
2,1,4,3,5,6,7,8,9,10

I know you can shuffle arrays but how do get uniques shuffles with maybe a seed number like srand to create

random groups of numbers between 10 and 1?

Thanks in advance


one number you can do with

//+------------------------------------------------------------------+
//| Return a random number from x to y                               |
//+------------------------------------------------------------------+
double MathRandRange(double x, double y)
{
   return(x+MathMod(MathRand(),MathAbs(x-(y+1))));
}


/* example
double rand=MathRandRange(1,10);  //output a number in the range of 1......  10
double rand=MathRandRange(10,20);  //output a number in the range of 10......  20
*/
 
bonechair:

I know you can shuffle arrays but how do get uniques shuffles with maybe a seed number like srand to create

random groups of numbers between 10 and 1?

Thanks in advance


Many possibilities. The following isn't necessarily the best: [edited because the original assumes the list is already unordered]

1. Fill an array with the numbers 1 to 10 (e.g. arr[0] =1, arr[1] = 2 etc)

2. Pick two random numbers n1 and n2 between 0 and 9

3. Swap the array items at positions n1 and n2, e.g. if n1 = 2 and n2 = 4 then after the first swap arr[2] = 5 and arr[4] = 3

4. Repeat steps 2 and 3 as many times as you feel necessary

Broadly equivalent to taking an ordered pack of cards and shuffling it.

 
bonechair: I know you can shuffle arrays but how do get uniques shuffles with maybe a seed number like srand to creat
  1. Use this and you would have found Shuffle array or random number - MQL4 forum posted 8 days ago.
  2. It uses MathRand. If you need to seed it use MathSrand
  3. If you just need random number (linear probabilities,) skip the array and just call Random()
 
deVries:
   return(x+MathMod(MathRand(),MathAbs(x-(y+1))));

MathRand returns a number [0 .. 32767] mapping that to [x .. y] with modulo will not produce a equal probabilities and using the low order digits (modulo) is the worst way for random numbers. See my reply to RaptorUK: Shuffle array or random number - MQL4 forum

 
WHRoeder:

MathRand returns a number [0 .. 32767] mapping that to [x .. y] with modulo will not produce a equal probabilities and using the low order digits (modulo) is the worst way for random numbers. See my reply to RaptorUK: Shuffle array or random number - MQL4 forum



In this case i don't agree that it makes a big difference

to test it i made this

//+------------------------------------------------------------------+
//|                                                random_number.mq4 |
//|                                        Copyright © 2014, deVries |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, deVries"
#property link      ""

#property indicator_chart_window

int k[10];
int i;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
//----
int rand;
while(i<500000){rand=MathRandRange(1,10);
  if (rand == 1) k[0]++;
  if (rand == 2) k[1]++;
  if (rand == 3) k[2]++;
  if (rand == 4) k[3]++;
  if (rand == 5) k[4]++;
  if (rand == 6) k[5]++;
  if (rand == 7) k[6]++;
  if (rand == 8) k[7]++;
  if (rand == 9) k[8]++;
  if (rand == 10) k[9]++;
  

i++;}



Comment(i,"   ",k[0]," ",k[1]," ",k[2]," ",k[3]," ",k[4]," ",k[5]," ",k[6]," ",k[7]," ",k[8]," ",k[9]);
  
//----
   return(0);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Return a random number betwen x and y                       |
//+------------------------------------------------------------------+
int MathRandRange(double x, double y)
{
   return(x+MathMod(MathRand(),MathAbs(x-(y+1))));
}

place it on a chart and change timeframe for other outcome to test it fast

maybe you can explain if you're right

there will always be a little difference in the numbers but i don't see one number is always very often the lowest or with more difference lower or higher then other numbers

 
Oh thank you WHRoeder will test that code out.
 

Can you answer the follow up question please:

https://www.mql5.com/en/forum/148768

 
deVries:


maybe you can explain if you're right

there will always be a little difference in the numbers but i don't see one number is always very often the lowest or with more difference lower or higher then other numbers


I think WHRoeder is correct about this one. The importance depends on the size of the random-number range, but it exists for all ranges. It will be trivial if calculating random numbers between 0 and 9, but very significant if calculating random numbers between 0 and 9999


For example, the following code uses your function to generate random numbers between 0 and 9999:

void start()
{
   int MaxRange = 10000, i;
   int arr[];
   ArrayResize(arr, MaxRange);
   
   // Do lots of interations of random numbers between 0 and MaxRange-1
   for (i = 0; i < 1000000; i++) {
      int v = MathRandRange(0, MaxRange - 1);
      arr[v]++;
   }
   
   // Write a TSV file of the number of incidences of each value
   int f = FileOpen("RandHistogram.tsv", FILE_BIN | FILE_WRITE);
   for (i = 0; i < MaxRange; i++) {
      string strX = "#" + i + "\t" + arr[i] + "\r\n";
      FileWriteString(f, strX, StringLen(strX));
   }
   FileClose(f);
   
   MessageBox("Done");
}

double MathRandRange(double x, double y)
{
   return(x+MathMod(MathRand(),MathAbs(x-(y+1))));
}

A chart of the output looks like the attached screenshot - there's very clearly a bias in the random generation.

The same bias exists if calculating random numbers between 0 and 9, but it's so small that it's probably not worth worrying about.



 
Assign your sequence of numbers to an array.

Assign random numbers to an array of the same size.
These wil be the new positions of the elements.
Sort this array and the original one in the same way.
(what you swap here, you swap there too)

No matter that you sort unique numbers.
The result will be random.

 
gchrmt4:


I think WHRoeder is correct about this one. The importance depends on the size of the random-number range, but it exists for all ranges. It will be trivial if calculating random numbers between 0 and 9, but very significant if calculating random numbers between 0 and 9999


For example, the following code uses your function to generate random numbers between 0 and 9999:

A chart of the output looks like the attached screenshot - there's very clearly a bias in the random generation.

The same bias exists if calculating random numbers between 0 and 9, but it's so small that it's probably not worth worrying about.




basically mathrand gives a random number in the range of 0 to 32767.

that means there are possible 32768 different numbers

if we take a remainder of all those numbers by dividing it with 10

we will get 3277 times outcome 0 and outcome 1,2,3,4,5,6,7 will also appear 3277 times

we will get 3276 times outcome 8 and 9

chance we get 1 is 3277/32768 * 100% = 10,00061 %

chance we get 8 is 3276/32769 * 100% = 9,99755 %

all almost 10 % finding a number between 0 and 9 is through the great number mathrand randomly returns almost equal

the only thing if you want equal probabilities then you can do for outcome equal possibillity

this

//+------------------------------------------------------------------+
//|                                                random_number.mq4 |
//|                                        Copyright © 2014, deVries |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, deVries"
#property link      ""

#property indicator_chart_window

int k[10];
int i;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
//----
int rand;
while(i<500000)
 {
   int kk=MathRand();
   if(kk>  32759)
       {
       while(kk>  32759)
           {kk=MathRand();}
       }    

   rand=(1+MathMod(kk,MathAbs(1-(10+1)))); 
 
 
  if (rand == 1) k[0]++;
  if (rand == 2) k[1]++;
  if (rand == 3) k[2]++;
  if (rand == 4) k[3]++;
  if (rand == 5) k[4]++;
  if (rand == 6) k[5]++;
  if (rand == 7) k[6]++;
  if (rand == 8) k[7]++;
  if (rand == 9) k[8]++;
  if (rand == 10) k[9]++;
  i++;
 }



Comment(i,"   ",k[0]," ",k[1]," ",k[2]," ",k[3]," ",k[4]," ",k[5]," ",k[6]," ",k[7]," ",k[8]," ",k[9]);
  
//----
   return(0);
  }
//+------------------------------------------------------------------+

but the outcome for all numbers will never be the same

throwing with a dice ?? with numbers 1 to 6 is like the same

Reason: