Comparing a variable to a range of values - c++

In mathematics, the notation 18 < age < 30 denotes that age must lie between the values 18 and 30. Is it possible to use this kind of notation in the if statement? For example, I've tried executing
if(18 < age < 30)
and I get weird output, so it's not quite right. Is there a way to do this or so I simply have to write
if(age > 18) /*blah*/;
else if(age < 30) /*same blah*/;

You can do:
if (18 < age && age < 30) /*blah*/;

Nobody answered as to what exactly happened with your code, so let me pick it apart.
Consider the single statement: bool result = 18 < age < 30;
We want to evaluate the right-hand expression: 18 < age < 30
There are two operators in this expression, and since they are identical, they both have the same priority, in this case, they are thus evaluated from left to right, therefore the expression is equivalent to:
(18 < age) < 30
So let's first examine the left-hand member: 18 < age, it yields a boolean which is either true or false, typically represented as an integral value respectively 1 or 0. Thus the expression can be summed up as:
{0,1} < 30
which is always true.
Therefore, should you use assert(18 < age < 30); it would never backfire.
This implicit conversion between integral (and floating point) built-in types is really annoying...

A bit of template code can help here:
template <int min, int max> class range {
static bool contains(int i) { return min <= i && i < max; } // In C++, ranges usually are half-open.
};
int age = 23;
if (range<18,30>::contains(age)) { /****/ }

Is it possible to use this kind of notation in the if statement?
Yes, possible.
Desirable, hardly ever: programmers presume the behaviours described in other answers will always apply, so if you dramatically change the order of evaluation and the meaning of an expression then it will really badly confuse them and - sooner or later - cause grief. If you have a very small project with few staff, and they're basically looking to create a domain-specific language in C++, where the domain's notation is really much more readable and familiar using this notation (maybe they're mathematicians not programmers anyway), then you might in extremis consider something like I present below, though it's still likely to cause trouble.
I've implemented this kind of thing before years ago as an exploratory exercise. If you wish to do so but need help getting started: off the top of my head (i.e. doubtless buggy), consider:
struct Weird
{
Weird(int n) : n_(n), b_is_meaningful_(false) { }
Weird(int n, bool b) : n_(n), b_is_meaningful_(true), b_(b) { }
int n_;
bool b_is_meaningful_;
bool b_;
};
Weird operator<(Weird lhs, Weird rhs)
{
if (lhs.b_is_meaningful_)
if (!lhs.b_) // effectively, anding with something already known false...
return Weird(rhs.n_, false);
return Weird(rhs.n_, lhs.n_ < rhs.n_);
}
Basically, you hack it around until you can:
Weird x = 10;
assert(6 < x < 20 < 30 < Weird(80));
At each point, the operator< creates a new Weird object with the Right Hand Side (rhs) value, while updating the boolean state on the assumption that you're effectively anding together a set of comparisons. If you really want to make a mess, you can support all kinds of things in C++, you might have a crack at say "x == 6 || 3 || 56" for fun...?

You can write a boolean expression as
((18 < age) && (age < 30))
An expression such as the above can be used whereever a boolean expression is acceptable, for example (but not limited to):
if((18 < age) && (age < 30)) { ... }
or
bool age_in_range = ((18 < age) && (age < 30));
Note that the above expression uses short-circuit evaluation of operator &&.

I know of no way to do exactly as you ask but the normal way is
Use the and operator
if (age > 18 && age <30)

Or write yourself a nice set of functions that does this
template <typename type>
bool in_range_[none|both|low|high]<type>( value, min, max )
to cater to all types of boundary included/or not
(don't use this for floating point)
In C++0x you could allow and disallow all other possibilities using the "delete" keyword that disables functions for overloads such as < float/double >

Related

how to find if a varibles value is between 2 numbers [duplicate]

In mathematics, the notation 18 < age < 30 denotes that age must lie between the values 18 and 30. Is it possible to use this kind of notation in the if statement? For example, I've tried executing
if(18 < age < 30)
and I get weird output, so it's not quite right. Is there a way to do this or so I simply have to write
if(age > 18) /*blah*/;
else if(age < 30) /*same blah*/;
You can do:
if (18 < age && age < 30) /*blah*/;
Nobody answered as to what exactly happened with your code, so let me pick it apart.
Consider the single statement: bool result = 18 < age < 30;
We want to evaluate the right-hand expression: 18 < age < 30
There are two operators in this expression, and since they are identical, they both have the same priority, in this case, they are thus evaluated from left to right, therefore the expression is equivalent to:
(18 < age) < 30
So let's first examine the left-hand member: 18 < age, it yields a boolean which is either true or false, typically represented as an integral value respectively 1 or 0. Thus the expression can be summed up as:
{0,1} < 30
which is always true.
Therefore, should you use assert(18 < age < 30); it would never backfire.
This implicit conversion between integral (and floating point) built-in types is really annoying...
A bit of template code can help here:
template <int min, int max> class range {
static bool contains(int i) { return min <= i && i < max; } // In C++, ranges usually are half-open.
};
int age = 23;
if (range<18,30>::contains(age)) { /****/ }
Is it possible to use this kind of notation in the if statement?
Yes, possible.
Desirable, hardly ever: programmers presume the behaviours described in other answers will always apply, so if you dramatically change the order of evaluation and the meaning of an expression then it will really badly confuse them and - sooner or later - cause grief. If you have a very small project with few staff, and they're basically looking to create a domain-specific language in C++, where the domain's notation is really much more readable and familiar using this notation (maybe they're mathematicians not programmers anyway), then you might in extremis consider something like I present below, though it's still likely to cause trouble.
I've implemented this kind of thing before years ago as an exploratory exercise. If you wish to do so but need help getting started: off the top of my head (i.e. doubtless buggy), consider:
struct Weird
{
Weird(int n) : n_(n), b_is_meaningful_(false) { }
Weird(int n, bool b) : n_(n), b_is_meaningful_(true), b_(b) { }
int n_;
bool b_is_meaningful_;
bool b_;
};
Weird operator<(Weird lhs, Weird rhs)
{
if (lhs.b_is_meaningful_)
if (!lhs.b_) // effectively, anding with something already known false...
return Weird(rhs.n_, false);
return Weird(rhs.n_, lhs.n_ < rhs.n_);
}
Basically, you hack it around until you can:
Weird x = 10;
assert(6 < x < 20 < 30 < Weird(80));
At each point, the operator< creates a new Weird object with the Right Hand Side (rhs) value, while updating the boolean state on the assumption that you're effectively anding together a set of comparisons. If you really want to make a mess, you can support all kinds of things in C++, you might have a crack at say "x == 6 || 3 || 56" for fun...?
You can write a boolean expression as
((18 < age) && (age < 30))
An expression such as the above can be used whereever a boolean expression is acceptable, for example (but not limited to):
if((18 < age) && (age < 30)) { ... }
or
bool age_in_range = ((18 < age) && (age < 30));
Note that the above expression uses short-circuit evaluation of operator &&.
I know of no way to do exactly as you ask but the normal way is
Use the and operator
if (age > 18 && age <30)
Or write yourself a nice set of functions that does this
template <typename type>
bool in_range_[none|both|low|high]<type>( value, min, max )
to cater to all types of boundary included/or not
(don't use this for floating point)
In C++0x you could allow and disallow all other possibilities using the "delete" keyword that disables functions for overloads such as < float/double >

Is it defined behaviour to assign to function call in or in if (C++17)

During a codebase refactor I found code like this:
void myFunction (std::map<int, int> my_map)
{
int linked_element;
if (my_map[linked_element = firstIndex] != 0
|| my_map[linked_element = secondIndex] != 0)
{
// do some stuff with linked_element
}
}
Or
void myFunction (std::set<int> my_set)
{
int linked_element;
if (my_set.find(linked_element = firstIndex) != my_set.end()
|| my_set.find(linked_element = secondIndex) != my_set.end())
{
// do some stuff with linked_element
}
}
From what I understood the aim of that was to avoid checking 2 times (first when entering in the if, second when assigning the variable).
I can understand that depending on which side of the || is true linked_element will be assigned to the right value but this still feels kind of bad to me.
Is this kind of behaviour defined?
This behavior is well defined by the order of evaluation.
First, the linked_element = firstIndex assignment happens. This expression returns the value of firstIndex, that is then used as an argument for the subscript operator on my_map (i.e., my_map[linked_element = firstIndex]). The return value from that expression is checked against the != 0 condition. If it's true, the other side of the || operator is not evaluated due to short-circuit logic. If it's false, the same story happens on the other side of the operator.
Whether or not it's a good practice to write code in such a style is a different question though. Personally speaking, I'd prioritize readability and maintainability over this micro-optimization unless it's a super-critical piece of the program, but it's a matter of opinion, I guess.
In original code behavior is well defined, since operator || evaluates first argument and if this is evaluated to false evaluates second argument.
BUT: Assignment there is confusing and many (probably all) static analyzes tools will complain about this. So I would reflector this code in this way, so it would require less brain power to read:
void doSomeStuff(const std::set<int>& my_set, int linked_element)
{
.....
}
void myFunction (const std::set<int>& my_set)
{
if (my_set.find(firstIndex) != my_set.end())
{
doSomeStuff(my_set, firstIndex);
} else if (my_set.find(secondIndex) != my_set.end()) {
doSomeStuff(my_set, secondIndex);
}
}
Since you had to ask question about this code this proves that original version is bad from maintainer point of view. Code which requires lots of focus to understand is costly in maintenance.
BTW this fragment of code:
if (my_map[linked_element = firstIndex] != 0
looks suspicious. I have even more suspensions seeing set-version.
This looks like that someone do not understand how operator[] works for maps. If value for key do not exist, default value is introduced to map. So checking for default value 0 seem like attempt to adders this issue. Possibly my_map.count(firstIndex) should be used.
An alternate version, assuming firstIndex and secondIndex are literal values (like 2 and 7), or are otherwise known relative to some invalid third index value:
void myFunction (std::set<int> & my_set)
{
int linked_element =
my_set.contains (firstIndex) ? firstIndex :
my_set.contains (secondIndex) ? secondIndex :
thirdIndex;
if (linked_element != thirdIndex)
{
// do some stuff with linked_element
}
}
If the indices are not known then a std::optional<int> can step in here too.
If pre-C++20, replace .contains() with .count().
Bigger concerns with the original code are:
the pass-by-value of a potentially large container (never assume COW)
map[index] silently adds the index to the map if not present

why this type of If-statement gives true in CPP [duplicate]

In mathematics, the notation 18 < age < 30 denotes that age must lie between the values 18 and 30. Is it possible to use this kind of notation in the if statement? For example, I've tried executing
if(18 < age < 30)
and I get weird output, so it's not quite right. Is there a way to do this or so I simply have to write
if(age > 18) /*blah*/;
else if(age < 30) /*same blah*/;
You can do:
if (18 < age && age < 30) /*blah*/;
Nobody answered as to what exactly happened with your code, so let me pick it apart.
Consider the single statement: bool result = 18 < age < 30;
We want to evaluate the right-hand expression: 18 < age < 30
There are two operators in this expression, and since they are identical, they both have the same priority, in this case, they are thus evaluated from left to right, therefore the expression is equivalent to:
(18 < age) < 30
So let's first examine the left-hand member: 18 < age, it yields a boolean which is either true or false, typically represented as an integral value respectively 1 or 0. Thus the expression can be summed up as:
{0,1} < 30
which is always true.
Therefore, should you use assert(18 < age < 30); it would never backfire.
This implicit conversion between integral (and floating point) built-in types is really annoying...
A bit of template code can help here:
template <int min, int max> class range {
static bool contains(int i) { return min <= i && i < max; } // In C++, ranges usually are half-open.
};
int age = 23;
if (range<18,30>::contains(age)) { /****/ }
Is it possible to use this kind of notation in the if statement?
Yes, possible.
Desirable, hardly ever: programmers presume the behaviours described in other answers will always apply, so if you dramatically change the order of evaluation and the meaning of an expression then it will really badly confuse them and - sooner or later - cause grief. If you have a very small project with few staff, and they're basically looking to create a domain-specific language in C++, where the domain's notation is really much more readable and familiar using this notation (maybe they're mathematicians not programmers anyway), then you might in extremis consider something like I present below, though it's still likely to cause trouble.
I've implemented this kind of thing before years ago as an exploratory exercise. If you wish to do so but need help getting started: off the top of my head (i.e. doubtless buggy), consider:
struct Weird
{
Weird(int n) : n_(n), b_is_meaningful_(false) { }
Weird(int n, bool b) : n_(n), b_is_meaningful_(true), b_(b) { }
int n_;
bool b_is_meaningful_;
bool b_;
};
Weird operator<(Weird lhs, Weird rhs)
{
if (lhs.b_is_meaningful_)
if (!lhs.b_) // effectively, anding with something already known false...
return Weird(rhs.n_, false);
return Weird(rhs.n_, lhs.n_ < rhs.n_);
}
Basically, you hack it around until you can:
Weird x = 10;
assert(6 < x < 20 < 30 < Weird(80));
At each point, the operator< creates a new Weird object with the Right Hand Side (rhs) value, while updating the boolean state on the assumption that you're effectively anding together a set of comparisons. If you really want to make a mess, you can support all kinds of things in C++, you might have a crack at say "x == 6 || 3 || 56" for fun...?
You can write a boolean expression as
((18 < age) && (age < 30))
An expression such as the above can be used whereever a boolean expression is acceptable, for example (but not limited to):
if((18 < age) && (age < 30)) { ... }
or
bool age_in_range = ((18 < age) && (age < 30));
Note that the above expression uses short-circuit evaluation of operator &&.
I know of no way to do exactly as you ask but the normal way is
Use the and operator
if (age > 18 && age <30)
Or write yourself a nice set of functions that does this
template <typename type>
bool in_range_[none|both|low|high]<type>( value, min, max )
to cater to all types of boundary included/or not
(don't use this for floating point)
In C++0x you could allow and disallow all other possibilities using the "delete" keyword that disables functions for overloads such as < float/double >

Fastest way to check equality with tolerance within a range?

The following function compare two arrays, and returns true if all elements are equal taking in account a tolerance.
// Equal
template<typename Type>
bool eq(const unsigned int n, const Type* x, const Type* y, const Type tolerance)
{
bool ok = true;
for(unsigned int i = 0; i < n; ++i) {
if (std::abs(x[i]-y[i]) > std::abs(tolerance)) {
ok = false;
break;
}
}
return ok;
}
Is there a way to beat the performances of this function ?
Compute abs(tolerance) outside the loop.
You might try unrolling the loop into a 'major' loop and a 'minor' loop where the 'minor' loop's only jump is to its beginning and the 'major' loop has the 'if' and 'break' stuff. Do something like ok &= (x[i]-y[i] < abstol) & (y[i]-x[i] < abstol); in the minor loop to avoid branching -- note & instead of &&.
Then partially unroll and vectorise the minor loop. Then specialise for whatever floating-point types you're actually using and use your platform's SIMD instructions to do the minor loop.
Think before doing this, of course, since it can increase code size and thereby have ill effects on maintainability and sometimes the performance of other parts of your system.
You can avoid those return variable assignments, and precalculate the absolute value of tolerance:
// Equal
template<typename Type>
bool eq(const unsigned int n, const Type* x, const Type* y, const Type tolerance) {
const Type absTolerance = std::abs(tolerance);
for(unsigned int i = 0; i < n; ++i) {
if (std::abs(x[i]-y[i]) > absTolerance) {
return false;
}
}
return true;
}
Also, if you know the tolerance will be always possitive there's no need to calculate its absolute value. If not, you may take it as a precondition.
I would do it like this, you can roll a C++03 version with class functors also, it will be more verbose but should be equally efficient:
std::equal(x, x+n, y, [&tolerance](Type a, Type b) -> bool { return ((a-b) < tolerance) && ((a-b) > -tolerance); }
Major difference is dropping the abs: depending on Type and how abs is implemented you might get a conditional execution path extra, with lots of branch mispredictions, this should certainly avoid that. The duplicate calculation of a-b will likely be optimized away by the compiler (if it deems necessary).
Of course, it introduces an extra operator requirement for Type and if operators < or > are slow, it might be slower then abs (measure it).
Also, std::equal is a standard algorithm doing all that looping and early breaking for you, it's always a good idea to use a standard library for this. It's usually nicer to maintain (in C++11 at least) and could get optimized better because you clearly show intent.

c++ Performance Of And Operator With Example

I was wondering if the && operator works in a cascading manor. Compare the following implementations of a rectangle collision check.
inline bool RectInRect(RECT one,RECT two){
if(one.left < two.right)
if(one.right > two.left)
if(one.top < two.bottom)
if(one.bottom > two.top)
return true;
return false;
}
inline bool RectInRect(RECT one,RECT two){
return (one.left < two.right && one.right > two.left &&
one.top < two.bottom && one.bottom > two.top);
}
Are these both the same or will the top one operate faster?
Yes, the second version essentially boils down to the first. The relevant property of the operator is that it’s short-circuited: the second operand is only evaluated if necessary, that is, if the first operand evaluates to true. Otherwise, the whole expression will always evaluate to false so there’s no need to look at the second operand.
This behaviour is guaranteed and is analogous, but the other way round, for || / or.
There is no way that the version on the top be faster then the one below. Also for me the statement below is way clearer so my advice is - better use the second version.