I'm trying to find a nice solution for following problem:
My input is a set of boolean variables b0 to bn and
a set of if statements calling some function in case the expression (conjunction of my boolean vars) is true.
For example:
void test(bool b0, bool b1, bool b2, bool b3, bool b4) {
if(b0&&b1) { action1(); }
if(b0&&b1&&b3) { action2(); }
if(b0&&b1&&b4) { action2(); }
if(b0&&b2) { action3(); }
}
Obviously this code could be optimized in order to minimize the number of comparisons.
For instance:
void test(bool b0, bool b1, bool b2, bool b3, bool b4) {
if(b0) {
if(b1) {
action1();
if(b3) { action2(); }
if(b4) { action2(); }
}
if(b2) { action3(); }
}
}
Is there an algorithm that solves/optimizes this problem (maybe even in an optimal way)?
It's obvious that it can be represented as a graph, table, etc. but somehow I still couldn't find a smart solution.
Update: I think I did not explain the problem well enough. Think about the problem as a truth table with multiple outputs. The inputs are the boolean variables and the outputs are the actions. So it is not just something that can be solved with KV map or Quine–McCluskey algorithm. Guess it is more complicated.
The table for the example above would be (I left out the "no output" cases):
b0| b1| b2| b3| b4 || action1 | action2 | action3
1 | 1 | 0 | 0 | 0 || 1 | 0 | 0
1 | 1 | 0 | 1 | 0 || 1 | 1 | 0
1 | 1 | 0 | 0 | 1 || 1 | 1 | 0
1 | 0 | 1 | 0 | 0 || 0 | 0 | 1
Don't optimise prematurely.
If you are thinking about such kind of optimizations you have to measure first. Make sure that this function is your hotspot in the production code. Thus,
Turn on the highest optimisation level (-O3)
Use a proper tool to locate hotspots, such as perf or Intel's vTune
Then if you find that this is your hotspot. Change it and measure again. You will be surprised in a lot of cases. It is quite possible, that the compiler will do this optimisation job for you.
Nevertheless, I think that the second version of your code can be read more fluently.
In general, if you need to deal with a bunch of boolean flags, merge them into a single uint32, which will allow you to test them fairly easily...
#include <cstdint>
enum Flags
{
kB0 = 1 << 0,
kB1 = 1 << 1,
kB2 = 1 << 2,
kB3 = 1 << 3,
kB4 = 1 << 4,
kB5 = 1 << 5,
};
inline bool testFlagsSet(uint32_t testFlags, uint32_t flags)
{
return (testFlags & flags) == testFlags;
}
void test(uint32_t flags) {
if(testFlagsSet(kB0 | kB1, flags)) { action1(); }
if(testFlagsSet(kB0 | kB1 | kB3, flags)) { action2(); }
if(testFlagsSet(kB0 | kB1 | kB4, flags)) { action3(); }
if(testFlagsSet(kB0 | kB2, flags)) { action4(); }
}
You can ch:ek the difference between the approaches here: https://godbolt.org/z/3P06fL
Also worth noting that of the original two methods you posted, the second one is better: https://godbolt.org/z/YTbYxh
I understand what you are asking. There are optimizing tools available to help to transform such code. But basically, it is not necessary.
And your new code is not better. It has even 5 if-statements. Performance wise, the compiler's optimizer will take care. It will detect the common subexpression and optimize that away.
This should also be basically done by the software developer / designer. A peer review will detect that code and fix the semantic problem.
You know of course that boolean expressions can be minimized via Quine&McCluskey or others. But I understand that this is not your question.
Static code analysis by Coverity / QAC / SonarCube can detect it, but will not fix it. This needs to be done manually.
Or you need to evaluate source code optimizers like PVS Studio
Please check.
Related
My code looks like this:
/*
* A B
* 0 0 -> 1
* 0 1 -> 0
* 1 0 -> 0
* 1 1 -> 0
*/
#define A condition_1
#define B condition_2
if (A) {
// do nothing
} else {
if (B) {
// do nothing
} else {
// do something
}
}
Above I've reported the truth table for two conditions where 1 is true and 0 is false, is there a way to express the truth table into a single if-condition?
Your truth table represents a NOR (not or) operation. You can get that easily by combining logical NOT (!) with logical OR (||)
if (!(A || B)) {
}
PS. Please, don't use #define macros. It's very error-prone and tends to bite programmers who use it. Most often there are safer and more readable ways to perform what macro does.
Use:
if (!A && !B) {
// do something
}
Think, your truth table only returns 1 when both conditions are false (0 0 -> 1).
You can use ! in both to invert it.
If there is only one 1 in the table then it's essentially AND operation. If there is only one 0 then it's OR operation. If there are two of both then you can make it an equality operation.
When you know which operation to chose your next step is to figure out which operands should be negated. For AND both operands must turn to 1 to produce 1 (1 AND 1 = 1), so negate those who would otherwise produce 0. For OR it's opposite, negate those who would produce 1 when trying to have 0 a s result (0 OR 0 = 0)
For equality operation bear in mind that bool can either be true or false, so there are only two values. If you try to use something that is not a bool for a logical operand then there would be problems. With that in mind when you want to produce equality negate any of the operands if originally they don't produce correct result (0 == 0 = 1 and also 1 == 1 = 1, if you understand me).
In your particular case we have only one 1 in the table so it's an AND operation. Both operands are 0 for this 1 outcome so we have to negate both of them:
!A && !B
First of all, I know the problem with the code and how to get it to work. I'm mainly looking for an explanation why my output is what it is.
The following piece of code replicates the behaviour:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("start");
for(int i = 0; i < 70000; i++) {
if((i % 2000) == 0)
Serial.println(i);
}
}
Obviously the for loop will run forever because i will overflow at 32,767. I would expect it to overflow and print -32000.
Expected| Actually printed
0 | 0
2000 | 2000
4000 | 4000
... | ...
30000 | 30000
32000 | 32000
-32000 | 33536
-30000 | 35536
It looks like it prints the actual iterations, since if you overflow and count to -32000 you would have 33536 iterations, but I can't figure out how it's able to print the 33536.
The same thing happens every 65536 iterations:
95536 | 161072 | 226608 | 292144 | 357680
97536 | 163072 | 228608 | 294144 | 359680
99072 | 164608 | 230144 | 295680 | 361216
101072 | 166608 | 232144 | 297680 | 363216
EDIT
When I change the loop to add 10.000 every iteration and only print every 1.000.000 to speed it up the Arduino crashes (or at least, the prints stop) at '2.147.000.000'. Which seems to point to the 32-bit idea of svtag**
EDIT2
The edits I made for the 2.147.000.000-check:
void loop() {
Serial.println("start");
for(int i = 0; i < 70000; i+=10000) {
if((i % 1000000) == 0)
Serial.println(i);
}
}
They work in the same trend with the previous example, printing 0, 1000000, 2000000,...
However, when I update the AVR package from 1.6.17 to the latest 1.6.23 I get only 0's. The original example (% 2000 & i++) still gives the same output.
The compiler may have automatically casted the i to usigned int when you are doing the println or the value is going to the wrong overload. Try using Serial.println((int)i);
I am having trouble with my while loop terminating, even though a 5 or 6 isn't entered. Thanks!
int main() {
char choice;
int num = 0;
bool quit = false;
while (!quit)
{
std::cin>>num;
std::cout << num << '\n';
if(num == 5 || 6)
{
quit = true;
}
}
return EXIT_SUCCESS;
}
All right. You're encountering a bit of misunderstanding on your part, aggravated by a wart in the C language.
The == operator only compares values, it won't look in a list. It returns 1 or 0, which represents true or false respectively.
The | operator is the "binary-or" operator. It performs an operation comparing the values of two numbers bit by bit ( this is known as a bit-wise operation ). The | sets the bit in the final number to 1 if the same bit is 1 in either of the given numbers.
0b00 | 0b00 -> 0b0000
0b10 | 0b00 -> 0b0010
0b00 | 0b10 -> 0b0010
0b10 | 0b11 -> 0b0011
The || operator is the "logical-or" operator, and returns 1, meaning true, if either of its given expressions yield 1. If the left expression yields 1, it doesn't bother to execute the right one ( this is known as short circuiting ).
HOWEVER, when they were initially creating C, they did something that has plagued the language since. They made == bind tighter than | in the order of operations ( also known as operator precedence ). This means ( 1 == 2 | 3 ) does not mean "the result of comparing 1 to the result of taking the binary or of 2 and 3", but instead means "the result of taking the binary or of ( the result of comparing 1 and 2 ) and 3".
It means ( ( 1 == 2 ) | 3 ), where ( 1 == ( 2 | 3 ) ) is what most would expect before being made aware of this oddity.
All this taken together, your if statement means:
if ( num == 5 ) | 6:
quit()
Which is very likely to quit for numbers other than 5 or 6! :)
Your if statement isn't doing what you think it does. Try this:
if(num == 5 || num == 6)
"Or" in C++ is || not a single bar.
I think you meant to put this: if(num == 5 || num == 6) as your condition || 6 is a non zero value and so evaluates to true everytime.
while practicing recursive functions, I have written this code for fibonacci series and (factorial) the program does not run and shows the error "Control reaches end of non-void function" i suspect this is about the last iteration reaching zero and not knowing what to do into minus integers. I have tried return 0, return 1, but no good. any suggestions?
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <ctime>
using namespace std;
int fib(int n) {
int x;
if(n<=1) {
cout << "zero reached \n";
x= 1;
} else {
x= fib(n-1)+fib(n-2);
return x;
}
}
int factorial(int n){
int x;
if (n==0){
x=1;
}
else {
x=(n*factorial(n-1));
return x;
}
}
Change
else if (n==1)
x=1;
to
else if (n==1)
return 1;
Then fib() should work for all non-negative numbers. If you want to simplify it and have it work for all numbers, go with something like:
int fib(int n) {
if(n<=1) {
cout << "zero reached \n";
return 1;
} else {
return fib(n-1)+fib(n-2);
}
}
"Control reaches end of non-void function"
This is a compile-time warning (which can be treated as an error with appropriate compiler flags). It means that you have declared your function as non-void (in this case, int) and yet there is a path through your function for which there is no return (in this case if (n == 1)).
One of the reasons that some programmers prefer to have exactly one return statement per function, at the very last line of the function...
return x;
}
...is that it is easy to see that their functions return appropriately. This can also be achieved by keeping functions very short.
You should also check your logic in your factorial() implementation, you have infinite recursion therein.
Presumably the factorial function should be returning n * factorial(n-1) for n > 0.
x=(factorial(n)*factorial(n-1)) should read x = n * factorial(n-1)
In your second base case (n == 1), you never return x; or 'return 1;'
The else section of your factorial() function starts:
x=(factorial(n)*factorial(n-1));
This leads to infinite recursion. It should be:
x=(n*factorial(n-1));
Sometimes, your compiler is not able to deduce that your function actually has no missing return. In such cases, several solutions exist:
Assume
if (foo == 0) {
return bar;
} else {
return frob;
}
Restructure your code
if (foo == 0) {
return bar;
}
return frob;
This works good if you can interpret the if-statement as a kind of firewall or precondition.
abort()
(see David RodrĂguez's comment.)
if (foo == 0) {
return bar;
} else {
return frob;
}
abort(); return -1; // unreachable
Return something else accordingly. The comment tells fellow programmers and yourself why this is there.
throw
#include <stdexcept>
if (foo == 0) {
return bar;
} else {
return frob;
}
throw std::runtime_error ("impossible");
Not a counter measure: Single Function Exit Point
Do not fall back to one-return-per-function a.k.a. single-function-exit-point as a workaround. This is obsolete in C++ because you almost never know where the function will exit:
void foo(int&);
int bar () {
int ret = -1;
foo (ret);
return ret;
}
Looks nice and looks like SFEP, but reverse engineering the 3rd party proprietary libfoo reveals:
void foo (int &) {
if (rand()%2) throw ":P";
}
Also, this can imply an unnecessary performance loss:
Frob bar ()
{
Frob ret;
if (...) ret = ...;
...
if (...) ret = ...;
else if (...) ret = ...;
return ret;
}
because:
class Frob { char c[1024]; }; // copy lots of data upon copy
And, every mutable variable increases the cyclomatic complexity of your code. It means more code and more state to test and verify, in turn means that you suck off more state from the maintainers brain, in turn means less maintainer's brain quality.
Last, not least: Some classes have no default construction and you would have to write really bogus code, if possible at all:
File mogrify() {
File f ("/dev/random"); // need bogus init
...
}
Do not do this.
There is nothing wrong with if-else statements. The C++ code applying them looks similar to other languages. In order to emphasize expressiveness of C++, one could write for factorial (as example):
int factorial(int n){return (n > 1) ? n * factorial(n - 1) : 1;}
This illustration, using "truly" C/C++ conditional operator ?:, and other suggestions above lack the production strength. It would be needed to take measures against overfilling the placeholder (int or unsigned int) for the result and with recursive solutions overfilling the calling stack. Clearly, that the maximum n for factorial can be computed in advance and serve for protection against "bad inputs". However, this could be done on other indirection levels controlling n coming to the function factorial. The version above returns 1 for any negative n. Using unsigned int would prevent dealing processing negative inputs. However, it would not prevent possible conversion situation created by a user. Thus, measures against negative inputs might be desirable too.
While the author is asking what is technically wrong with the recursive function computing the Fibonacci numbers, I would like to notice that the recursive function outlined above will solve the task in time exponentially growing with n. I do not want to discourage creating perfect C++ from it. However, it is known that the task can be computed faster. This is less important for small n. You would need to refresh the matrix multiplication knowledge in order to understand the explanation. Consider, evaluation of powers of the matrix:
power n = 1 | 1 1 |
| 1 0 | = M^1
power n = 2 | 1 1 | | 1 1 | | 2 1 |
| 1 0 | * | 1 0 | = | 1 1 | = M^2
power n = 3 | 2 1 | | 1 1 | | 3 2 |
| 1 1 | * | 1 0 | = | 2 1 | = M^3
power n = 4 | 3 2 | | 1 1 | | 5 3 |
| 2 1 | * | 1 0 | = | 3 2 | = M^4
Do you see that the matrix elements of the result resemble the Fibonacci numbers? Continue
power n = 5 | 5 3 | | 1 1 | | 8 5 |
| 3 2 | * | 1 0 | = | 5 3 | = M^5
Your guess is right (this is proved by mathematical induction, try or just use)
power n | 1 1 |^n | F(n + 1) F(n) |
| 1 0 | = M^n * | F(n) F(n - 1) |
When multiply the matrices, apply at least the so-called "exponentiation by squaring". Just to remind:
if n is odd (n % 2 != 0), then M * (M^2)^((n - 1) / 2)
M^n =
if n is even (n % 2 == 0), then (M^2)^(n/2)
Without this, your implementation will get the time properties of an iterative procedure (which is still better than exponential growth). Add your lovely C++ and it will give a decent result. However, since there is no a limit of perfectness, this also can be improved. Particularly, there is a so-called "fast doubling" for the Fibonacci numbers. This would have the same asymptotic properties but with a better time coefficient for the dependence on time. When one say O(N) or O(N^2) the actual constant coefficients will determine further differences. One O(N) can be still better than another O(n).
I recently came across some functions where you can pass multiple enums like this:
myFunction(One | Two);
Since I think this is a really elegant way I tried to implement something like that myself:
void myFunction(int _a){
switch(_a){
case One:
cout<<"!!!!"<<endl;
break;
case Two:
cout<<"?????"<<endl;
break;
}
}
now if I try to call the function with One | Two, I want that both switch cases get called. I am not really good with binary operators so I dont really know what to do. Any ideas would be great!
Thanks!
For that you have to make enums like :
enum STATE {
STATE_A = 1,
STATE_B = 2,
STATE_C = 4
};
i.e. enum element value should be in power of 2 to select valid case or if statement.
So when you do like:
void foo( int state) {
if ( state & STATE_A ) {
// do something
}
if ( state & STATE_B ) {
// do something
}
if ( state & STATE_C ) {
// do something
}
}
int main() {
foo( STATE_A | STATE_B | STATE_C);
}
Bitwise operators behave well only with powers of 2:
0010
| 0100
------
0110 // both bits are set
0110
& 0100
------
0100 // nonzero, i.e. true: the flag is set
If you try to do the same with arbitrary numbers, you'll get unexpected results:
0101 // 5
| 1100 // 12
------
1101 // 13
Which contains the possible (arbitrary) numbers as set flags: 0001 (1), 0100 (4), 0101 (5), 1000 (8), 1001 (9), 1100 (12), 1101 (13)
So instead of giving two options, you just gave six.
Usually arguments that are combined that way are flags (a value with a single bit set) with a decimal value of 1, 2, 4, 8, etc. Assuming that One and Two follow this rule, you cannot use a switch to check for both. Switches only follow one path. Your combined argument does not equal One or Two, but a combination of them (1 | 2 == 3). You can check to see if One or Two is set like this:
if (_a & One)
{
}
if (_a & Two)
{
}
Remember that a standard enum without explicit values will just count upwards, not use the next bit. If your next defined value is Three, it will likely equal 3 which is not a value of a single bit, and will then act as if you had passed both flags (One | Two) to the function. You'll need to set the values of the enum yourself.
You must split the possible "tokens" (non-overlapping of course... use power of 2):
if (_a & One) { ... }
Not elegant really do what you want with 1 switch statement: split using if statements.
You are better off doing it with a set of if statements ...
ie
if ( _a & ONE )
{
// Do stuff.
}
if ( _a & TWO )
{
// Do other stuff.
}
edit: You could also do it in a switch statement but it would be a nightmare. Youd need something like this
switch( _a )
{
case ONE:
// Handle ONE.
break;
case TWO:
// Handle TWO.
break;
case ONE | TWO:
// Handle ONE.
// Handle TWO.
break;
};
Its relatively sane for only 2 options but once you get more than that it starts to balloon out of control. If you have 32-options you'd have a switch statement that would be unlikely to fit on any machine. All in the "if" solution is much cleaner and far more sane :)