Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

general pattern for implementing truth tables

Tags:

c++

Is there a good general pattern for implementing truth tables?

I am re-working some legacy code (C++) and just realized that the function I am working with amounts to a truth table with 3 binary inputs and 8 possible outputs. Here is an example of two of the eight tests and corresponding outputs:

// - + +
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;

Basically I am wondering if there is a cleaner, more maintainable/extensible* way to set this up.

  • What if another input is added? Then the number of if statements needed would be 16, which in my view, would be too cumbersome to manage with the current pattern.
  • What if several of the input combos should map to the same output?

*The codebase is an ecosystem model used in academia, so maintenance and extension amount to similar things depending on the perspective of the coder.

like image 242
tbc Avatar asked Jun 18 '12 17:06

tbc


People also ask

What is the first step in constructing a truth table?

Three skills are necessary in order to do so: Producing an initial list of all permutations of truth and falsity assigned to the sentence letters in the sentence. Determining which columns in a truth table can be filled in at a given stage. Determining what truth values to fill into a given column.

What are the rules of truth table?

A truth table is a mathematical table used to determine if a compound statement is true or false. In a truth table, each statement is typically represented by a letter or variable, like p, q, or r, and each statement also has its own corresponding column in the truth table that lists all of the possible truth values.


2 Answers

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: // + + +
}
like image 105
CAFxX Avatar answered Oct 16 '22 18:10

CAFxX


An array is a table.

A sequence of boolean truth values is a binary number.

Arrays are indexed by number.

Sooooo .....

You could define a function for each calculation:

// - + + == 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);
}

// ...

Then declare an array of function pointers:

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

Then index into the array using the boolean conditions as binary digits:

func_type f = funcs[ (int(prevdst5 < 0.0)<<2) | (int(dst5 < 0.0)<<1) | int(nextdst5 > 0.0) ];
thawpct = f(prevdst5, dst5, nextdst5);
  • What if another input is added? (Then the number of tests would be 16, which in my view would be cumbersome to manage with the current pattern)

You double the size of the array and add f8, f9 etc. if different calculations are needed, but you only add the new test once, in the array index:

func_type f = funcs[ (cond<<3) | (int(prevdst5 < 0.0)<<2) | (int(dst5 < 0.0)<<1) | int(nextdst5 > 0.0) ];
  • What if several of the input combos should map to the same output?

Store the same function pointer at several elements of the array:

func_type funcs[8] = {
  f1, f2, f3, f1, f1, // ...
};
like image 33
Jonathan Wakely Avatar answered Oct 16 '22 18:10

Jonathan Wakely