2

Given a float, how to map it to an enum like

{FAIL, POOR, OK, GOOD, EXCELLENT, PERFECT}

if the divisions aren't even.

0.0-0.4 is FAIL
0.4-0.6 is POOR
...
0.8-0.999.. is EXCELLENT
1.0 is PERFECT

The float is a rating value calculated from all the played levels in a game. It ranges from 0..1, both inclusive. There are normally no more than about 10 divisions needed, but the spacings are subject to tuning during development.

I'm currently using a stack of if..else statements. Is that the right way to do it? It seems a bit brittle.

willc2
  • 38,991
  • 25
  • 88
  • 99

2 Answers2

6

Use an array of structs - either statically allocated or dynamic - and then a simple routine to search it - if its small just iterate, if its large you can do binary search.

As you know the minimum (0.0) and maximum (1.0) you only need to store the upper-bound of the range and enum value. E.g:

typedef enum {FAIL, POOR, OK, GOOD, EXCELLENT, PERFECT} Rating;

typedef struct
{
   float upperBound;
   Rating score;
} RatingDivision;

static RatingDivision Divisions[] =
{
   { 0.4, FAIL },
   { 0.6, POOR },
   ...
   { 0.999, EXCELLENT },
   { 1.0, PERFECT }
};

Now sizeof(Divisions)/sizeof(RatingDivision) will tell you the number of entries (needed for binary search), or just iterate until the value you're looking for is <= Divisions[i].upperBound returning Divisions[i].score or the upperBound reaches 1.0 with no match and handle the error.

CRD
  • 52,522
  • 5
  • 70
  • 86
3

You could use parallel arrays: use an array of threshold float values, and an array of enum values of the same size; then you could use a single short loop, checking each value in the float array and returning the enum value once the threshold is crossed.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186