C 真值表的优化实现

C 真值表的优化实现,c,algorithm,truthtable,karnaugh-map,C,Algorithm,Truthtable,Karnaugh Map,我已经确定了一个真相表,如下所示 prev_state| input1 | input2 |next_state| Action (def/new) |(Disable/Enable)|(Off/On)| | def | D | Off | def | Nothing def | D | On | def | Nothing def | E

我已经确定了一个真相表,如下所示

prev_state| input1         | input2 |next_state| Action
(def/new) |(Disable/Enable)|(Off/On)|          |
def       | D              | Off    | def      | Nothing
def       | D              | On     | def      | Nothing
def       | E              | Off    | def      | Nothing
def       | E              | On     | new      | call function1
new       | D              | Off    | def      | call function2
new       | D              | On     | def      | call function2
new       | E              | Off    | def      | call function2
new       | E              | On     | new      | Nothing
我想知道实现这一目标所需的最少检查次数是多少

我的想法是使用一种类似以下的方法:

    00| 01| 11| 10 
  -----------------
0 | A | A | B | A |  
  -----------------
1 | C | C | A | C |  
  -----------------
其中A不对应任何内容,B调用函数1,C调用函数2

根据我所看到的,你有2个A和一个A的组合,一个A总共有3个 1换B 和2个C的组合

这是否意味着比较的最小数量是3+1+2=6? 但是因为A什么都不做,所以最低限度的实现需要 只有B和C的3种组合

测试实现

if (prev_state == new && input1 == disable) {
    function2();
}
else if (prev_state == new && input2 == Off) {
    function2();
}
else if (input1 == enable && input2 == On) {
    function1();
}
现在我明白了,上面哪一个更好,还是这一个更好:

if ((prev_state == new && input1 == disable) || (prev_state == new && input2 == Off)) {
    function2();
}
else if (input1 == enable && input2 == On) {
    function1();
}
感谢你们提出了一个查找表,它是O(1),但占用了内存空间。
我现在意识到我更希望有一个不使用额外内存的解决方案。您是否同意使用卡诺图是导出最小比较量的有效方法?

如果行为是静态的,则无法进行测试,您可以

  • 使用一个三维数组,其中每个值都是下一个状态和动作的耦合,第一个维度是上一个状态0/1,第二个输入1 D/E->0/1,第三个输入2 off/on->0/1

  • 但是,由于您的输入非常有限,您也可以只在一个=
    prev_state*4+input1*2+input2
    中编码这3个索引,并使用大小为8的简单向量。正如Schwern在评论中所建议的,您也可以对
    prev_state*4+input1*2+input2


如果行为是静态的,那么进行测试是无用的,您可以

  • 使用一个三维数组,其中每个值都是下一个状态和动作的耦合,第一个维度是上一个状态0/1,第二个输入1 D/E->0/1,第三个输入2 off/on->0/1

  • 但是,由于您的输入非常有限,您也可以只在一个=
    prev_state*4+input1*2+input2
    中编码这3个索引,并使用大小为8的简单向量。正如Schwern在评论中所建议的,您也可以对
    prev_state*4+input1*2+input2

我想知道你需要达到的最低检查次数是多少

零。使用查找表

void f_Nothing(void) {
  ; // do nothing
}

void f_function1(void) {
  ;  // something interesting
}

void f_function2(void) {
  ;  // something interesting
}

int main(void) {

  typedef void (*fun_type)(void);

  fun_type f[2][2][2] = { //
      {{f_Nothing, f_Nothing}, {f_Nothing, f_function1}}, 
      {{f_function2, f_function2}, {f_function2, f_Nothing}}};
  bool prev_state, input1, input2;
  //...
  f[prev_state][input1][input2]();

OP后来评论道

我想知道你需要达到的最低检查次数是多少

零。使用查找表

void f_Nothing(void) {
  ; // do nothing
}

void f_function1(void) {
  ;  // something interesting
}

void f_function2(void) {
  ;  // something interesting
}

int main(void) {

  typedef void (*fun_type)(void);

  fun_type f[2][2][2] = { //
      {{f_Nothing, f_Nothing}, {f_Nothing, f_function1}}, 
      {{f_function2, f_function2}, {f_function2, f_Nothing}}};
  bool prev_state, input1, input2;
  //...
  f[prev_state][input1][input2]();

OP后来评论道


您可以删除一些重复测试,但在实践中是否会产生很大的差异取决于编译器的优化

if (prev_state == new) {
    if (input1 == disable || input2 == Off) {
        function2();
    }
} else {
    if (input1 == enable && input2 == On) {
        function1();
    }
}
或:


您可以删除一些重复测试,但在实践中是否会产生很大的差异取决于编译器的优化

if (prev_state == new) {
    if (input1 == disable || input2 == Off) {
        function2();
    }
} else {
    if (input1 == enable && input2 == On) {
        function1();
    }
}
或:


我会做下面的事情

int check = (int)((prev_state == new) << 2 | (input1 == E)<<1 | (input2 == on));

/*def       | E              | On     | new      | call function1 == 3
  new       | D              | Off    | def      | call function2 == 4
  new       | D              | On     | def      | call function2 == 5
  new       | E              | Off    | def      | call function2 == 6 */

if (check == 4 || check == 5 || check == 6)
  function2();
else if (check == 3)
  function1();

intcheck=(int)((prev_state==new)我会做下面的事情

int check = (int)((prev_state == new) << 2 | (input1 == E)<<1 | (input2 == on));

/*def       | E              | On     | new      | call function1 == 3
  new       | D              | Off    | def      | call function2 == 4
  new       | D              | On     | def      | call function2 == 5
  new       | E              | Off    | def      | call function2 == 6 */

if (check == 4 || check == 5 || check == 6)
  function2();
else if (check == 3)
  function1();

int check=(int)((prev_state==new)而不是向量,开关/案例是否也可以执行?是的,在第二种解决方案中,也可以执行开关/case@Schwern只是我喜欢数据驱动编程;-)与矢量不同,开关/案例是否也可以执行?是的,在第二种解决方案中,也可以执行开关/case@Schwern只是我喜欢数据驱动编程;-)只是好奇:为什么要在
/
或`的末尾说````注释?fun\u type f[2][2][2]={/`是为了鼓励自动格式化,使初始值设定项保持在下一行-我觉得更好。@bruno编写一个可编译的解决方案需要时间-这是我在改进OP的问题后开始的。谢谢你的回答。我意识到现在我忘了指定我正在寻找一个理想情况下不使用额外内存的解决方案。我专注于关于使用卡诺图系统地减少比较的想法是否有效。@Satraps提示:张贴的目标是“最少检查次数”.现在,如果一个小时后还有一个额外的限制?如果你需要改变目标,那就这样吧。但是移动的目标可能会导致一个不明确的问题。只是好奇:为什么“\`”?在/或
`结尾处发表评论
乐趣类型f[2][2]={/`是为了鼓励自动格式化,使初始值设定项保持在下一行-我觉得更好。@bruno编写一个可编译的解决方案需要时间-这是我在改进OP的问题后开始的。谢谢你的回答。我意识到现在我忘了指定我正在寻找一个理想情况下不使用额外内存的解决方案。我专注于g关于使用卡诺图系统性地减少比较的想法是否有效。@Satraps提示:张贴的目标是“最少检查次数”。现在,如果一小时后有额外的限制?如果你需要更改目标,就这样吧。但是移动的目标可能会导致一个不清楚的问题。