Range-bound switch?

 

How can I do something like this better;

int zero_to_hundred=x,shift;
if(zero_to_hundred<=10){shift=4;}else{
if(zero_to_hundred<=20){shift=5;}else{
if(zero_to_hundred<=30){shift=8;}else{
if(zero_to_hundred<=40){shift=4;}else{
if(zero_to_hundred<=50){shift=9;}else{
if(zero_to_hundred<=60){shift=3;}else{
if(zero_to_hundred<=70){shift=4;}else{
if(zero_to_hundred<=80){shift=8;}else{
if(zero_to_hundred<=90){shift=2;}else{shift=7;}}}}}}}}}

A switch operator comes to mind, but I would have to make 100 cases (1 to 100) as the switch operator apparently only allows constants.

Other ideas?

 

Is there a functional connection between zero_to_hundred and the result (shift)?

Like for example (not corresponding to your numbers!!) shift = (int)(c2*zero_to_hundred/10 + c1);
 
Roel13: t I would have to make 100 cases (1 to 100)
  1. Don't paste code
    Play video
    Please edit your post.
    For large amounts of code, attach it.

  2. int Shift(int v){       // 0 1 2 3 4 5 6 7 8 9 10
      static int shift[] = {   0,4,4,4,4,4,4,4,4,4,4, // 10
                               5,5,5,5,5,5,5,5,5,5,5, // 20
                               8,8,8,8,8,8,8,8,8,8,8, // 30
                               4,4,4,4,4,4,4,4,4,4,4, // 40
                               9,9,9,9,9,9,9,9,9,9,9, // 50
                               3,3,3,3,3,3,3,3,3,3,3, // 60
                               4,4,4,4,4,4,4,4,4,4,4, // 70
                               8,8,8,8,8,8,8,8,8,8,8, // 80
                               2,2,2,2,2,2,2,2,2,2,2, // 90
                               7,7,7,7,7,7,7,7,7,7,7} // 100
      return shift[v];
    }
    int zero_to_hundred=x,shift = Shift(x);

 
WHRoeder:
  1. Play videoFor large amounts of code, attach it.


1. Ouch, good reminder.

2. Cool thanks!

 
gooly:

Is there a functional connection between zero_to_hundred and the result (shift)?

Like for example (not corresponding to your numbers!!) shift = (int)(c2*zero_to_hundred/10 + c1);
No, regrettably not. Otherwise indeed a formula may work. Another one I like is something like  if((double)some_var/100==(int)some_var/100){...}  - i.e. only every 100th step.
 

For those using this (VERY COOL - thanks again WHRoeder) solution, two small bugfixes (to avoid doubling up on ten's + ';');

int Shift(int v){       // 0 1 2 3 4 5 6 7 8 9 10
  static int shift[] = {   0,4,4,4,4,4,4,4,4,4,4, // 10
                             5,5,5,5,5,5,5,5,5,5, // 20
                             8,8,8,8,8,8,8,8,8,8, // 30
                             4,4,4,4,4,4,4,4,4,4, // 40
                             9,9,9,9,9,9,9,9,9,9, // 50
                             3,3,3,3,3,3,3,3,3,3, // 60
                             4,4,4,4,4,4,4,4,4,4, // 70
                             8,8,8,8,8,8,8,8,8,8, // 80
                             2,2,2,2,2,2,2,2,2,2, // 90
                             7,7,7,7,7,7,7,7,7,7}; // 100
  return shift[v];
}
int zero_to_hundred=x,shift = Shift(x);
 
Roel13:

For those using this (VERY COOL - thanks again WHRoeder) solution, two small bugfixes (to avoid doubling up on ten's + ';');

#define SHIFT(x) shifts[((x)-1)/10]
//--- globals
int shifts[]=  {/*<=10*/4, /*<=20*/5, /*<=30*/8, /*<=40*/4, /*<=50*/9, /*<=60*/3, /*<=70*/4, /*<=80*/8, /*<=90*/2, /*<=100*/7 };

int zero_to_hundred=x,shift=SHIFT(x);

 
angevoyageur:

Wow that is also a cool solution. I wonder which one would win in processing time. I think I will test it as it is an important part of the code. Thank you angevoyageur and WHRoeder

 
1 Trillion runs, milisecond precision start/stop and 3 executions average on freshly started MT4 terminal rev 765

Solution 1 by WHRoeder;

2015.01.30 08:23:35.213    Speedtest1 EURUSD,M5: Execution time: 36645ms   (int Shift(int v){...})
2015.01.30 08:24:27.252    Speedtest1 EURUSD,M5: Execution time: 36926ms   (int Shift(int v){...})
2015.01.30 08:32:48.855    Speedtest1 EURUSD,M5: Execution time: 36301ms   (int Shift(int v){...})

Solution 2 by angevoyageur;

2015.01.30 08:36:11.076    Speedtest2 EURUSD,M1: Execution time: 35210ms   ("define SHIFT(x)"...)
2015.01.30 08:37:08.371    Speedtest2 EURUSD,M1: Execution time: 35225ms   ("define SHIFT(x)"...)
2015.01.30 08:37:47.766    Speedtest2 EURUSD,M1: Execution time: 35256ms   ("define SHIFT(x)"...)
2015.01.30 08:53:08.860    Speedtest2 EURUSD,M1: Execution time: 35240ms   ("define SHIFT(x)"...)

And a 3rd solution (simple "static int Shift[]" array declaration at the top and call Shift[x]) based on the first;

2015.01.30 08:39:21.252    Speedtest3 EURUSD,M1: Execution time: 35318ms   (static int Shift[]={...})
2015.01.30 08:40:18.516    Speedtest3 EURUSD,M1: Execution time: 35272ms   (static int Shift[]={...})
2015.01.30 08:41:14.076    Speedtest3 EURUSD,M1: Execution time: 35272ms   (static int Shift[]={...})

And the same as the 3rd but with no "static";

2015.01.30 08:43:26.212    Speedtest4 EURUSD,M1: Execution time: 35256ms   (int Shift[]={...})
2015.01.30 08:44:04.802    Speedtest4 EURUSD,M1: Execution time: 35272ms   (int Shift[]={...})
2015.01.30 08:44:47.423    Speedtest4 EURUSD,M1: Execution time: 35318ms   (int Shift[]={...})

And a 4rd solution based on the second but with a slightly simplified form based on the first;

2015.01.30 08:50:28.725    Speedtest5 EURUSD,M1: Execution time: 35256ms   ("define SHIFT(x) Shift[x]" + simple int array)
2015.01.30 08:51:08.158    Speedtest5 EURUSD,M1: Execution time: 35318ms   ("define SHIFT(x) Shift[x]" + simple int array)
2015.01.30 08:52:22.165    Speedtest5 EURUSD,M1: Execution time: 35303ms   ("define SHIFT(x) Shift[x]" + simple int array)

So... drum roll please... the winner is angevoyageur's code;

#define SHIFT(x) shifts[((x)-1)/10]
//--- globals
int shifts[]=  {/*<=10*/4, /*<=20*/5, /*<=30*/8, /*<=40*/4, /*<=50*/9, /*<=60*/3, /*<=70*/4, /*<=80*/8, /*<=90*/2, /*<=100*/7 };

And in the code use;
int shift = SHIFT(x);

Interestingly enough, changing "(x)" to "x" makes it a bit slower! I can see the defenisive coding bit in using "(x)" (think passing of caculations), but how about that, it increases speed too.

Another interesting sidenote? After testing this, I set the Windows process priority of terminal32.exe to "High" in task manager (right click the process) and re-ran solution 2 a few times;

2015.01.30 08:54:53.963    Speedtest2 EURUSD,M1: Execution time: 35100ms    (Solution 2, Windows "high" process priority)
2015.01.30 08:56:09.560    Speedtest2 EURUSD,M1: Execution time: 35100ms    (Solution 2, Windows "high" process priority)
2015.01.30 08:57:21.558    Speedtest2 EURUSD,M1: Execution time: 35178ms    (Solution 2, Windows "high" process priority)

It's nicely faster indeed. Stability? Don't know...

Now, testing the solution 2 code for correctness;

#define SHIFT(x) shifts[(x-1)/10]
//--- globals
int shifts[]=  {/*<=10*/1, /*<=20*/2, /*<=30*/3, /*<=40*/4, /*<=50*/5, /*<=60*/6, /*<=70*/7, /*<=80*/8, /*<=90*/9, /*<=100*/10 };

void OnStart(){
int time_start=0,time_end=0;

time_start=(int)GetTickCount();

  for(int i=0;i<=100;i++){
    Print(SHIFT(i));
  }
}

It is fully correct :)

The only gotcha (which is covered in WHRoeder's code but not angevoyageur's one) is to watch out for is that SHIFT(0) - usually not used - returns "1", i.e. so if you run the test code above (0 to 100), you will get 11x1,10x2,10x3,...,10x9,10x10. I can live with this - I would never use SHIFT(0) as my optimize range starts from 1 and ends at 100.

And, offcourse, if you do not have nicely defined ranges (/10, /5, etc.) then you would have to look at using WHRoeder's solution. In this case I could recommend using this variation of it (based on the speed testing);

// Variable declarations
//               1 2 3 4 5 6 7 8 9 10
int Shift[] = {0,4,4,4,4,4,4,4,4,4,4, // 10
                 5,5,5,5,5,5,5,5,5,5, // 20
                 8,8,8,8,8,8,8,8,8,8, // 30
                 4,4,4,4,4,4,4,4,4,4, // 40
                 9,9,9,9,9,9,9,9,9,9, // 50
                 3,3,3,3,3,3,3,3,3,3, // 60
                 4,4,4,4,4,4,4,4,4,4, // 70
                 8,8,8,8,8,8,8,8,8,8, // 80
                 2,2,2,2,2,2,2,2,2,2, // 90
                 7,7,7,7,7,7,7,7,7,7}; // 100

void OnStart(){
  int shift = Shift[x];   // And offcourse in functions, you can just use "Shift[x]" directly.
}


---
Not financial advice. For testing purposes only. Do not use on live account.
 
  1. Roel13: So... drum roll please... the winner is angevoyageur's code;
    His solution only allows 10 cases. Your original request was for 100.
    Roel13: I would have to make 100 cases (1 to 100)

  2. Your third solution is just mine without the function call overhead.
  3. In any case, the differences is in the noise. Using a function allows 100 separate items or 10, without having to modify any other code. Always write modular code. Optimize only if and when you have a problem and can measure the difference.
 

Hi WHRoeder,

2. Yes, hence I wrote "based on the first;" - the first is yours :)
3. Not sure I follow, can you explain what you mean by "noise"?

Reason: