8

是否有一个很好的通用模式来实现真值表?

我正在重新处理一些遗留代码(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,在我看来,这对于当前的模式来说太麻烦了。
  • 如果几个输入组合应该映射到同一个输出怎么办?

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

4

3 回答 3

9
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: // + + +
}
于 2012-06-18T17:27:40.483 回答
4

数组是一个表。

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

数组按数字索引。

呜呜呜……

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

// - + + == 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, // ...
};
于 2012-06-18T17:21:40.733 回答
0

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

这样,您将拥有一个 3 维地图(所有维度的大小为 2)

于 2012-06-18T17:22:29.207 回答