【问题标题】:How to simplify if statements如何简化 if 语句
【发布时间】:2021-11-20 05:16:59
【问题描述】:

如何简化下面的 if 语句?,我正在尝试实现可能最有效的代码。

// doSomething based on x value and y value   
void doSomething(x int, y int) {

    //x not zero and y not zero
    if (x != 0 && y != 0) {
      //do a

      //do b if x greater or equal y
      //else do c
      if (x >= y) {
          //do b
      } else (x < y) {
          //do c
      }

      return;
        
    }

    //do b if x not zero and y zero
    if (x != 0 && y == 0) {
        //do b
        return;
    }

    //do e if both x and y zero
    if (x == 0 && y == 0) {
        //do e
        return;
    }
}

最简洁有效的简化方法是什么?

【问题讨论】:

  • 使用else ifelse 语句肯定会有所帮助。如果操作正确,您可以消除所有 return 语句。
  • 在开始简化代码之前,您需要修复代码。例如,你有if x!=0 &amp;&amp; y!=0,在if 里面你有if (x==0 &amp;&amp; y!=0)。第二个if 永远不可能是真的,因为你已经验证了x!=0
  • 查看链接的答案 您可以使用卡诺图不仅用于比较,还可以用于简化布尔表达式 ...
  • 这是什么语言的?尽管大多数语言具有相对相似的结构,但它们在条件、模式匹配、switch case、字典等细节上有所不同,并且重写这种 if 森林的“最佳”方式可能因语言而异。

标签: c algorithm if-statement


【解决方案1】:

历史:

问题中的代码已多次更改。此答案基于original version of the code。该代码如下所示,经过最低限度的修改,使其成为可编译的 C 代码:

void original(int x, int y)
{
    if (x == y && x != 0 && y != 0) {
        // do a
        // do b
        return;
    }

    if (x < y && x != 0 && y != 0) {
        // do a
        // do c
        return;
    }

    if (x > y && x != 0 && y != 0) {
        // do a
        // do b
        return;
    }

    if (x != 0 && y == 0) {
        // do a
        // do b
        return;
    }

    if (x == 0 && y != 0) {
        // do a
        // do d
        return;
    }

    if (x == 0 && y == 0) {
        // do e
        return;
    }
}

动机:

原始代码的优点是它清楚地涵盖了所有可能的输入组合。

前三个if 语句处理xy 非零的情况(x==yx&lt;yx&gt;y 分别处理)。然后剩下的三个if 语句处理一个或两个都为零的情况。这涵盖了一切。

原代码的缺点是:

  1. 许多比较重复多次,例如y != 0 被检查四次。鉴于分支语句在当代(2021 年)处理器中往往很耗时,因此需要避免冗余比较1
  2. 代码违反了DRY principle。具体来说,do a 出现在五个位置,do b 出现在三个位置。因此,对代码的任何重构都应尝试消除重复。

1) 优化器可能能够减少比较次数。但是,如果没有真正的代码,这很难测试。

用嵌套的if 语句重构:

如果我们首先关注 DRY 原则,我们注意到a 出现在 6 个代码块中的 5 个中。只有e 的情况不会调用a。所以合乎逻辑的选择是先处理e。这导致以下代码结构:

if (x == 0 && y == 0) {
    // do e
} else {
    // do a
    // everything else (note that either x is not zero, or y is not zero)
}

在“其他一切”中,我们有三次do b,一次是do c,一次是do d。所以下一步是处理cd,只留下b。重构后的代码如下所示:

void nestedIf(int x, int y)
{
    if (x == 0 && y == 0) {
        // do e
    } else {
        // do a

        if (x == 0) {   
            // do d
        } else {
            if (y != 0 && x < y) {
                // do c
            } else {
                // do b
            }
        }
    }
}

用早期的return 语句重构:

一些编码标准坚持一个函数只能从一个位置返回。嵌套的if 代码满足该要求,但代价是由于嵌套而有点混乱。使用早期返回消除了嵌套,并且可能允许ae 的代码在没有附加函数的情况下内联实现(假设它们每个只有几行)。重构后的代码如下所示:

void earlyReturn(int x, int y)
{
    if (x == 0 && y == 0) {
        // do e
        return;
    }

    // do a

    if (x == 0) {   // x is zero and y is not zero
        // do d
        return;
    }

    if (y != 0 && x < y) {  // x and y are both not zero, and x < y
        // do c
        return;
    }

    // do b
}

【讨论】:

    【解决方案2】:

    假设 a()b()e() 具有相同的类型 (fxtype)

    fxtype *fx[4] = { e, NULL, b, a }; // NULL when x==0, y!=0
    fx[2*!!x + !!y](x, y);
    

    a 更改为包括c()b()

    int a(int x, int y) {
        // do previous a()
        if (x < y) c(x, y); else b(x, y);
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      就目前而言,您的代码相当于:

      if (x == 0)
      {
        if (y == 0)
          do e
      }
      else if (y != 0)
      {
        if (x < y)
          do a,c
        else
          do a,b
      }
      

      特别是:

      • 如果x=0 &amp;&amp; y!=0y=0 &amp;&amp; x!=0,则什么也不做;
      • //do b if x not zero and y zero//do d if x zero and y not zero 两个分支在您的代码中无法访问。

      【讨论】:

        猜你喜欢
        • 2014-06-18
        • 2021-12-07
        • 1970-01-01
        • 2015-09-12
        • 1970-01-01
        • 2020-03-15
        • 2019-10-06
        相关资源
        最近更新 更多