实现真值表的一般模式

时间:2012-06-18 17:13:38

标签: c++

实施真值表是否有良好的一般模式?

我正在重新处理一些遗留代码(C ++),并且意识到我正在使用的函数相当于一个包含3个二进制输入和8个可能输出的真值表。以下是八个测试中的两个和相应输出的示例:

// - + +
if ( (prevdst5 < 0.0) && (dst5 > 0.0) && (nextdst5 > 0.0) ){
    thawpct = (dst5 / (dst5 - prevdst5));
}

// - - +
if ( (prevdst5 < 0.0) && (dst5 < 0.0) && (nextdst5 > 0.0) ){
    thawpct = (nextdst5 / (nextdst5 - dst5));
}

// other cases...

return thawpct;

基本上我想知道是否有更清晰,更易维护/可扩展的方法来设置它。

  • 如果添加了其他输入怎么办?那么所需的if语句数量将是16,在我看来,使用当前模式进行管理会非常麻烦。
  • 如果几个输入组合应该映射到相同的输出怎么办?

*代码库是学术界使用的生态系统模型,因此根据编码器的观点,维护和扩展等同于类似事物。

3 个答案:

答案 0 :(得分:8)

int condition = ( prev >= 0 ? ( 1<<0 ) : 0 ) + 
                ( cur >= 0  ? ( 1<<1 ) : 0 ) + 
                ( next >= 0 ? ( 1<<2 ) : 0 );

switch (condition) {
  case 0: // - - -
  case 1: // + - -
  case 2: // - + -
  case 3: // + + -
  case 4: // - - +
  case 5: // + - +
  case 6: // - + +
  case 7: // + + +
}

答案 1 :(得分:4)

数组是一个表。

布尔真值序列是二进制数。

数组按数字编制索引。

Sooooo .....

您可以为每个计算定义一个函数:

// - + + == 0 1 1 == 3
inline double f3(double prev, double curr, double next)
{
  return curr / (curr - prev);
}

// - - + == 0 0 1 == 1
inline double f1(double prev, double curr, double next)
{
   return next / (next - curr);
}

// ...

然后声明一个函数指针数组:

typedef double (*func_type)(double, double, double);
func_type funcs[8] = {
  f1, f2, // ...
};

然后使用布尔条件作为二进制数字索引到数组中:

func_type f = funcs[ (int(prevdst5 < 0.0)<<2) | (int(dst5 < 0.0)<<1) | int(nextdst5 > 0.0) ];
thawpct = f(prevdst5, dst5, nextdst5);
  
      
  • 如果添加了其他输入怎么办? (然后测试的数量将是16,在我看来,使用当前模式进行管理会很麻烦)
  •   

如果需要进行不同的计算,您可以将数组的大小加倍并添加f8f9等,但只需在数组索引中添加一次新测试:

func_type f = funcs[ (cond<<3) | (int(prevdst5 < 0.0)<<2) | (int(dst5 < 0.0)<<1) | int(nextdst5 > 0.0) ];
  
      
  • 如果几个输入组合应该映射到相同的输出怎么办?
  •   

将相同的函数指针存储在数组的多个元素中:

func_type funcs[8] = {
  f1, f2, f3, f1, f1, // ...
};

答案 2 :(得分:0)

您可以将3(或n)值的映射保存到需要执行的相应函数中。然后根据条件的true / false状态循环此映射中的函数并执行该函数。

这样你就会得到一个3维的地图(所有维度的大小都是2)