这个if-else声明能否变得更加清晰

时间:2010-10-25 12:59:50

标签: c++

我正在尝试改进C ++分配以提高效率。我是语言的初学者(也是一般的编程),所以我只使用我目前所知的(如果,其他)。我有一个将分数转换为等级的函数,因此任何低于30 = 1,30-49 = 2,50-79 = 3的等等......

以下是我的表现:

if (score1 <= 30) level1 = 1;
else if (score1 <= 49) level1 = 2;
else level1 = 3;

if (score2 <= 30) level2 = 1;
else if (score2 <= 49) level2 = 2;
else level2 = 3;

//etc...

有没有更好的方法来做到这一点,因为我知道这将需要为我的每一个分数换一个新线。

9 个答案:

答案 0 :(得分:13)

这取决于你的效率意味着什么。您可以保持数组中每个级别的限制

int level_limits[] = {0, 30, 49, 79, [...]};

int getLevel(int score)
{
   int level;
   for (level = 0; level < N_LEVELS; ++level)
       if (level_limits[level] > score)
            return level;
   return level; // or whatever should happen when you exceed the score of the top level
 }
 ...

 level1 = getLevel(score1);
 level2 = getLevel(score2);

......或类似的东西。

答案 1 :(得分:5)

创建一个传入乐谱的函数,然后返回该级别。此外,如果有很多,你应该创建一个分数和级别的数组。

for (x=0;x < num_scores;x++)
{
   level[x] = get_level(score[x]);
}

类似的东西。

答案 2 :(得分:5)

首先将用于计算级别的代码分解为单独的函数,比如get_level:

level1 = get_level(score1);
level2 = get_level(score2);

您可以通过不同方式实现get_level。

如果级别数很小,您可以使用线性搜索:

const int bounds[] = {30, 49, 79}; // Add more level bounds here.

int get_level(int score)
{
    const size_t NUM_BOUNDS = sizeof(bounds) / sizeof(*bounds);
    for (size_t i = 0; i < NUM_BOUNDS; ++i)
        if (score <= bounds[i])
            return i + 1;
    return NUM_BOUNDS + 1;
}

或者,如果您是STL粉丝:

#include <algorithm>
#include <functional>

const int bounds[] = {30, 49, 79}; // Add more level bounds here.

int get_level(int score)
{
    return std::find_if(bounds,
        bounds + sizeof(bounds) / sizeof(*bounds),
        std::bind2nd(std::greater_equal<int>(), score)) - bounds + 1;
}

如果您有多个级别,二分搜索可能更合适:

#include <algorithm>

const int bounds[] = {30, 49, 79}; // Add more level bounds here.

int get_level(int score)
{
    return std::lower_bound(bounds,
        bounds + sizeof(bounds) / sizeof(*bounds), score) - bounds + 1;
}

或者,如果您的级别数量相对较少,则使用与原始版本类似的if-else链:

int get_level(int score)
{
    if (score <= 30)
        return 1;
    else if (score <= 49)
        return 2;
    else if (score <= 79)
        return 3;
    return 4;
}

请注意,将返回放在单独的行上可以使您的程序更容易在调试器中进行跟踪。

答案 3 :(得分:4)

不,就效率而言,它已经过优化。

另一种风格。我建议将条件和陈述放在不同的行上:

if (score1 <= 30) {
    level1 = 1;
} else if (score1 <= 49) {
    level1 = 2;
} else if (score1 <= 79) {
    level1 = 3;
}

正如另一个答案所暗示的那样,另一个风格加上是将常见行为提取到函数中

答案 4 :(得分:2)

绝对最快的方式:

创建一个包含80个值的数组,每个可能得分一个。 使用每个可能分数的级别填充数组。

实施例: int score_array [80] = {1,1,1,1,...};

以下代码可为您提供每个分数的级别:

level2 = score_array [score2];

这将编译为一个机器指令。没有快得多。

答案 5 :(得分:2)

如果score具有“可管理”范围,那么以下内容如何?

// Convert score to level. Valid scores are in the range [0-79]
int score2level( int score ) {

    static const int level_table[ 80 ] = {
        1, 1, 1, ...     // 31 "1"s for range 0-30
        2, 2, 2, ...     // 19 "2"s for range 31-49
        3, 3, 3, ...     // 30 "3"s for range 50-79
    };

    assert( (0 <= score) && (score <= 79) );

    return level_table[ score ];
 }

动机是以预先填充的表为代价避免条件代码(ifelse)。对于3个级别来说可能是太多了,但是当级别数增加时,可能会提供帮助。

答案 6 :(得分:1)

  int getLevel(int score)
  {
      if(score<=30)
          return 1;
      int level=2,limit=49;
      while(score > limit)
      {
          limit+=30;
          level++;
      }
      return level;
  }  

  int score[]={35,25,67,56,78};
  int level[5];
  for(int i=0;i<5;i++)
      level[i]=getLevel(score[i]);

干杯:)

答案 7 :(得分:1)

您可以使用modulo和哈希表来实现一些代码风格的优雅。伪代码:

int getLevel(int num)
{
   hash_table = (30=>1, 49=>2, 79=>3);
   foreach threshold (keys hash_table) {
      if (num modulo (threshold + 1) == num) {
        return hash_table[threshold];
      }
   }
}

答案 8 :(得分:1)

如果手上的手指水平低于手指,则应使用Paul's建议。但是,如果级别数较大,则可以使用二进制搜索,如果级别阈值相当均匀(并且严格增加)。然后你可以接近对数运行时(我的意思是, 要求效率)。

这是查找表 - 建议和线性搜索之间的良好折衷,但同样,只有你有很多级别才能付出代价。

哦,顺便说一下,如果选择阈值的模式如何,你应该使用它而不是搜索正确的级别。