Alternative to multiple else if statements?

Hi all,

This is my first post so apologies in advance for any problems I may cause. I am in the process of a project design for college and have encountered a problem. My design involves different values being output for a specific range value that if entered. I am doing this using else if statements, however, i find this taking up a lot of space. I have attached a sample of the code to show what I mean.

Thanks in advance for any help I might receive.

a.png

In some dialects of C, a switch/case can specify ranges, but I'm not sure if the Arduino dialect allows this.

Image from Original Post so we don't have to download it. See this Image Guide

123e12e8136b8e26d3b617a1606aa6fdde4e0ffe.png

...R

Please don't post pictures of code. Post it as text between [code] [/code] tags (or use the code button </>). Your code shouldlook like thisand that also makes it easy to copy to a text editor.

If you organize the sequence of tests properly it will simplify the code. For example

if (num <= 100) {

}
else if (num <= 140) {

}
else if (num <= 180) {

}
// etc

...R

Robin2,

Your idea was tried and tested with the Arduino to good success, however, it still leaves me with a lot of memory being used. I was guided in the direction of a lookup table but due to no set increments in my data, this seems as though it would not be the right direction to pursue.

cooks_91:
it still leaves me with a lot of memory being used.

How much is "a lot" ?

Can the number of clicks be derived from the value in num by some mathematical formula?

Maybe something like this pseudo code

if n < 100
   0
else if n < 140
   1
else 
   ((n - 100) / 40) * 3

But the succession of IFs would probably be faster and may not use more memory

...R

This is the function I am working with, as can be seen there is no set sequence. Maybe this seems to be the only option I can do for the program.

int range_clicks(int num)
{
  int clicks;

  if(num <= 100)
  {
    clicks = 0; 
  }
  else if((num > 100) && (num <= 140))
  {
    clicks = 1;
  }
  else if((num > 140) && (num <= 180))
  {
    clicks = 3;
  }
  else if((num > 180) && (num <= 220))
  {
    clicks = 6;
  }
  else if((num > 220) && (num <= 260))
  {
    clicks = 9;
  }
  else if((num > 260) && (num <= 300))
  {
    clicks = 12;
  }
  else if((num > 300) && (num <= 340))
  {
    clicks = 15;
  }
  else if((num > 340) && (num <= 380))
  {
    clicks = 19;
  }
  else if((num > 380) && (num <= 420))
  {
    clicks = 23;
  }
  else if((num > 420) && (num <= 460))
  {
    clicks = 27;
  }
  else if((num > 460) && (num <= 500))
  {
    clicks = 31;
  }
  else if((num > 500) && (num <= 540))
  {
    clicks = 35;
  }
  else if((num > 540) && (num <= 580))
  {
    clicks = 40;
  }
  else if((num > 580) && (num <= 620))
  {
    clicks = 45;
  }
  else if((num > 620) && (num <= 660))
  {
    clicks = 50;
  }
  else if((num > 660) && (num <= 700))
  {
    clicks = 56;
  }
  else if((num > 700) && (num <= 740))
  {
    clicks = 62;
  }
  else if((num > 740) && (num <= 780))
  {
    clicks = 68;
  }
  else if((num > 780) && (num <= 820))
  {
    clicks = 74;
  }
  else if((num > 820) && (num <= 860))
  {
    clicks = 81;
  }
  else if((num > 860) && (num <= 900))
  {
    clicks = 88;
  }
  else if((num > 900) && (num <= 940))
  {
    clicks = 97;
  }
  else 
  {
    clicks = 105;
  }

return clicks;
}

The best solution is to use an array as a look up table.
One array has the sequence of thresholds in it, the other array holds the output numbers you want.
You search through the first array with a loop looking for a point where the current array value is lower than your target and the next array value is above it. When you find that point your output number is in the other array at that index you found that condition.
It is only a few lines.

was guided in the direction of a lookup table but due to no set increments in my data, th

Their are three different types of look up table

  1. orderd input disorderd output
  2. disorderd input orderd output
  3. disorderd input disorderd output

Your problem requires a look up table of type 3)

Thanks very much Grumpy Mike, this type of lookup table seems to be the ideal solution to my problem.

Untested but compiles okay so should work...

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  int a = analogRead(A0);
  switch(a)
  {
    case 0 ... 100:
    Serial.println("0-100");
    break;
    case 101 ... 200:
    Serial.println("101-200");
    break;
    case 201 ... 300:
    Serial.println("201-300");
    break;
    case 301 ... 400:
    Serial.println("301-400");
    break;
    case 401 ... 512:
    Serial.println("401-512");
    break;
    default:
    Serial.println("513-1023");
  }
}

From here

A follow up question in regard the lookup table, as my range is between two values is there anyway of doing this or will I have to put in each number individually into my lookup table. My input could be any number between 0-1000, with the output only effected in steps of 40.

You will only need the high end of each range i.e. 100, 140, 180 etc. Store them in increasing order. Iterate through the array until num is less than or equal to the stored array value. Then look up the corresponding value of clicks at the same position in the second array.

The way you were originally doing this doesn't seem like it would be consuming much memory but If space is really a problem I'd be tempted to pursue Robin2's idea and try to find (using Excel perhaps) a formula to derive clicks from num. You may want to consider putting your arrays in progmem q.v. in that scenario if remaining RAM is your problem.

What is your project supposed to do?

byte rc( int num ) {
    byte conv[ ] = { 0,  1,  3,  6,  9, 12, 15, 19, 23, 27,  31,  35, 
                    40, 45, 50, 56, 62, 68, 74, 81, 88, 97, 105, 105 };

    if( (num -= 101) < 0 )  return 0;
    return conv[(num / 40) + 1];
}

EDIT:
rc( ) returns a byte, not an int as I originally posted.
EDIT:
Also, you can take away the "+ 1" if you delete the "0" from the array. I guess that was some residue I overlooked. :slight_smile:

as my range is between two values is there anyway of doing this or will I have to put in each number individually into my lookup table.

I said
One array has the sequence of thresholds in it.

So that would be

int inputThreshold [] = {0, 100 , 140,  180, 220, 260, 300, 340, 380, 420, 460, 500, 540, ..... and so on

The output array like boolrules has it.
Then search the inputThreshold array until you find an index with inputThreshold [i ] greater than your input value and inputThreshold [ i+1 ] less that it. Then the clicks value is just conv[i ].
That will work for any set of numbers.

However boolrules has cleverly spotted that your threshold numbers go up in steps of 40 making your problem a type 1) lookup table. +1 to him.