Why can't we do three-way comparison in C++? [duplicate] - c++

This question already has answers here:
Comparing a variable to a range of values
(7 answers)
Closed 3 years ago.
To summarize it quickly, why isn't 2 < x < 9 equal to 2 < x && x < 9?
This is the test code I've written:
#include <iostream>
int main()
{
int nums[] = { 5 , 1, 10};
// We are gonna check if the number is in the range 2 - 9
for (auto e : nums)
{
if (2 < e < 9)
std::cout << "2 < " << e << " < 9" << std::endl;
if(2 < e && e < 9)
std::cout << "2 < " << e << " and " << e << " < 9" << std::endl;
}
std::cin.get();
}
Here is the output I'm getting:
2 < 5 < 9
2 < 5 and 5 < 9
2 < 1 < 9
2 < 10 < 9
It looks like only 2 < e && e < 9 works correctly.

The expression
2 < x < 9
is grouped as
(2 < x) < 9
And since 2 < x is either false (0) or true (1), and both are less than 9, it's always true.
So unless you use overloaded operators for a non-built-in type x (then a 3-way comparison would be possible if 2 < x were to return an instance of a proxy object on which < is defined), if you want to test if x is in the interval (2, 9) you need to write it the way you have.

Just because this language doesn't have that feature.
It could have been made to, but this would contrast with C in a non-compatible way.
C could have been made to, but the designers simply didn't do that.
You already have the correct way to do it.
Some different (and newer!) languages do support this.

the comparison operators in c++ takes as an argument two values.
when you are writing a<b it is the same as operator<(a,b).
and the return value of operator< is bool.
when you are calling a function in c++, it is computing the expression of its arguments and then passing it to that function, so calling a<b<c is same as
operator<(operator<(a,b),c)
basically, the answer to your question is that in c++ there is no comparison operator (less than, greater than...) that takes three arguments

If C++ chose to redefine a < b < c to better align with the mathematical notation, it would be ambiguous with the current meaning. The current meaning is a bit silly and is comparing bools with numbers, but there may be tricky code relying on this detail in production use.
And as C++ allows you to define your own types with operators, it would have to expose the new ternary < to you as well, so you could make one for your type. Which would open new cans of worms if you only define a binary < but no ternary < for your type - should the compiler start shouting at you?

C++ didn’t do it because that would have broken backward compatibility with C. So you would need to look another decade back for the answer.
I don’t know whether Brian Kernighan or Dennis Ritchie ever considered doing it the other way, or discussed their reasoning. I’m not aware of anyone requesting that specific feature. Their relational operators follow the same rules as other Algol-family languages.
One problem would have been that it makes the grammar ambiguous: 0 < x < 1 now has a very different meaning than (0 < x) < 1 or 0 < (x < 1). There are also the issue of how to parse a < b >= c or a < b == c. Remember, there was no Boolean type in K&R C. Logical operators returned int, since the result was presumed to be stored in a machine register.
Another possible reason behind it is that K&R C, according to its designers, is not a high-level language. Its basic operations generally correspond to machine instructions on the minicomputers it was developed on. So, a comparison was a machine instruction back then, and a double-comparison was not. It would’ve been strange, given the other choices they made, to introduce that particular syntactic sugar into the language just to make C code read a little more like a math paper.

Inside of if, there should be boolean condition. In 2 < x < 9, there are two conditions. And two conditions can't be calculated in C++ without operator between them. That's why we can't use 2 < x < 9.

Related

C++ code printing strange values [duplicate]

This question already has answers here:
Math-like chaining of the comparison operator - as in, "if ( (5<j<=1) )" [duplicate]
(4 answers)
Closed 8 years ago.
i am having a very silly but strange problem. When i am trying to compile and run the following code my compiler is printing "ggl" but i think it shouldn't. It is strange that after doing so much programming i am stuck here. What exactly is the problem? Can someone please help me out? Thanks in advance !!
#include <iostream>
using namespace std;
int main() {
int t=8;
if(1<t<5){
cout<<"ggl";
}
//cout<<aa;
return 0;
}
This line doesn't do what you think it does
if(1<t<5)
You would have to say
if (1 < t && t < 5)
The first version says
if ((1 < t) < 5)
Which evaluates to
if (true < 5)
if (1 < 5)
Which is always true.
Your if condition effectively says if ((1 < t) < 5), which is always true, because (1 < t) is either 1 or 0 (1 < 8 evaluates to 1).
Since chained comparisons do not (usually) work in C++, you'll need to check the condition differently:
if (1 < t && t < 5) {
cout << "ggl";
}
This
if(1<t<5)
does not do what you think it does. It does not determine whether t is between 1 and 5. You want
if ((1<t) && (t<5))
What it actually does is take the value (1<t) (which will 1 if 1<t and 0 otherwise), then see if that value is less than 5, which it always will be.

Finding the square of a number without multiplication [duplicate]

This question already has answers here:
Making a square() function without x*x in C++
(7 answers)
Closed 4 years ago.
I'm a beginner in programming and trying to learn C++ by the book Programming principles and practice using C++. In some parts of the book there are little exercises that you can try to do, one of this exercises is about calculating the square of a number, here is what my book says :
Implement square() without using the multiply operator, that is, do the x * x by repetead addition (start a variable result to 0 and add x to it x times).
I've already found a solution for this program but my first tentative was something like this :
#include <iostream>
int main()
{
int a = 0;
std::cout << "Enter an integer value : ";
std::cin >> a;
while (a < a * a)
{
a += a;
std::cout << a << "\n";
}
}
I know this code is wrong but I can't understand the output of the progam, if I enter 5 the program prints 10 20 30 40 50 until 8000, why the for loop doesn't stop when a is greater than its square ? I'm just curious to undersant why
Using multiplication when trying to avoid multiplication seems broken. What about this:
int r = 0;
for (int n = 0; n < a; ++n) {
r += a;
}
why the for loop doesn't stop when a is greater than its square ?
Because it never is. If you compare the graph of y=x^2 against the graph of y=x, you will see that the only time y=x is above, is when 0 < x < 1. That's never the case for integers1. Now, since we're talking about computers with limited storage here, there is a thing called overflow, which will cause a very large number to become a very small number. However, signed integer overflow is undefined behavior in C++. So once your loop gets to the point where overflow would happen, you cannot rely on the results.
1. Note that your loop is not set to stop just when a is greater than its square, but when it is greater than or equal to its square. So, your loop will actually stop if a is 0 or 1.

Collecting the 2-power decomposition of n (Python, C++) [duplicate]

This question already has answers here:
Base-2 (Binary) Representation Using Python
(2 answers)
Closed 9 years ago.
I am writing a quick program to decompose a number into powers of 2. Is this an efficient way to do it:
pows=[]
pos = 0
while n>0:
if n%2==1: pows.append(2**pos)
n/=2
pos+=1
I've written this in Python but I'm also interested in how it's done in C++.
I don't know if this is a "smart" way to do it or if it's considered horribly inefficient.
The most natural implementation in C++ would use a bit mask for
the powers of two, something like:
std::vector<unsigned> p2;
unsigned m = 1;
while ( m != 0 ) {
if ( (m & i) != 0 ) {
p2.push_back( m );
}
m <<= 1;
}
You certainly don't want to call the pow function each time in
the loop. A somewhat trickery way, which is likely faster
(since it will usually pass less times in the loop) would be:
std::vector<unsigned> p2;
std::cout << i << ": ";
while ( i != 0 ) {
unsigned n = i & i - 1;
p2.push_back( i ^ n );
i = n;
}
I would recommend the first (which is readily understandable)
unless the profiler really says you must use the second.
Any modern compiler is probably going to be smart enough to optimize this. Get your code to run correctly first, and worry about optimizing for speed after profiling (if it is too slow).

What is the difference between ! ( x < y ) and x >= y in C++?

Going through EASTL, I stumbled across a peculiar line of code. The following link shows the file with the line number of interest at 1870.
https://github.com/paulhodge/EASTL/blob/master/include/EASTL/algorithm.h
The code at that line is if(!(value < *i)). The comment says that "we always express value comparisons in terms of < or ==" without any explanation as to why this is so. There are also a few other areas where the same comment is placed but without any explanation.
Is there any benefit whatsoever to writing a comparison like that (maybe some context that I am overlooking)? If not, why did the author of EASTL deliberately wrote it in this particular fashion and even took the care to comment about it? Is consistency the only reason here?
It means you only need to provide < and == for container value types. It also means you reduce the amount of variability for those types (as all the algorithms use !(a<b) to mean a>=b and !(a==b) for a!=b); otherwise, you could have >= and != return inconsistent results.
In C++, you can overload the < operator so that it behaves differently than the opposite of >=, so they are not guaranteed to be equivalent.
Additionally, in any IEEE floating-point implementation, NaN < NaN is false, but so is NaN >= NaN, so !(NaN < NaN) is true even though NaN >= NaN is false.
I see at least one difference. If one of the numbers was QNAN (floating-point 0/0) then !(a < b) would've always return TRUE if any of a or b were QNAN, while it would've always returned false for a>=b
Using just the less-than operator, you can simulate all the other comparison operators. This makes it more consistent and allows you to use a single template parameter when you need to parameterize the comparison. The standard sorted containers and algorithms use std::less<T> as the default template comparator for example.
operation equivalent
x < y x < y
x > y y < x
x <= y !(y < x)
x >= y !(x < y)
x == y !(x < y) && !(y < x)
x != y (x < y) || (y < x)
For those operations where ordering is not important it's simpler and more efficient to use operator == instead.

What is the "-->" operator in C++?

After reading Hidden Features and Dark Corners of C++/STL on comp.lang.c++.moderated, I was completely surprised that the following snippet compiled and worked in both Visual Studio 2008 and G++ 4.4.
Here's the code:
#include <stdio.h>
int main()
{
int x = 10;
while (x --> 0) // x goes to 0
{
printf("%d ", x);
}
}
Output:
9 8 7 6 5 4 3 2 1 0
I'd assume this is C, since it works in GCC as well. Where is this defined in the standard, and where has it come from?
--> is not an operator. It is in fact two separate operators, -- and >.
The conditional's code decrements x, while returning x's original (not decremented) value, and then compares the original value with 0 using the > operator.
To better understand, the statement could be written as follows:
while( (x--) > 0 )
Or for something completely different... x slides to 0.
while (x --\
\
\
\
> 0)
printf("%d ", x);
Not so mathematical, but... every picture paints a thousand words...
That's a very complicated operator, so even ISO/IEC JTC1 (Joint Technical Committee 1) placed its description in two different parts of the C++ Standard.
Joking aside, they are two different operators: -- and > described respectively in §5.2.6/2 and §5.9 of the C++03 Standard.
x can go to zero even faster in the opposite direction in C++:
int x = 10;
while( 0 <---- x )
{
printf("%d ", x);
}
8 6 4 2
You can control speed with an arrow!
int x = 100;
while( 0 <-------------------- x )
{
printf("%d ", x);
}
90 80 70 60 50 40 30 20 10
;)
It's equivalent to
while (x-- > 0)
x-- (post decrement) is equivalent to x = x-1 (but returning the original value of x), so the code transforms to:
while(x > 0) {
x = x-1;
// logic
}
x--; // The post decrement done when x <= 0
It's
#include <stdio.h>
int main(void) {
int x = 10;
while (x-- > 0) { // x goes to 0
printf("%d ", x);
}
return 0;
}
Just the space makes the things look funny, -- decrements and > compares.
The usage of --> has historical relevance. Decrementing was (and still is in some cases), faster than incrementing on the x86 architecture. Using --> suggests that x is going to 0, and appeals to those with mathematical backgrounds.
Utterly geek, but I will be using this:
#define as ;while
int main(int argc, char* argv[])
{
int n = atoi(argv[1]);
do printf("n is %d\n", n) as ( n --> 0);
return 0;
}
while( x-- > 0 )
is how that's parsed.
One book I read (I don't remember correctly which book) stated: Compilers try to parse expressions to the biggest token by using the left right rule.
In this case, the expression:
x-->0
Parses to biggest tokens:
token 1: x
token 2: --
token 3: >
token 4: 0
conclude: x-- > 0
The same rule applies to this expression:
a-----b
After parse:
token 1: a
token 2: --
token 3: --
token 4: -
token 5: b
conclude: (a--)-- - b
This is exactly the same as
while (x--)
Anyway, we have a "goes to" operator now. "-->" is easy to be remembered as a direction, and "while x goes to zero" is meaning-straight.
Furthermore, it is a little more efficient than "for (x = 10; x > 0; x --)" on some platforms.
This code first compares x and 0 and then decrements x. (Also said in the first answer: You're post-decrementing x and then comparing x and 0 with the > operator.) See the output of this code:
9 8 7 6 5 4 3 2 1 0
We now first compare and then decrement by seeing 0 in the output.
If we want to first decrement and then compare, use this code:
#include <stdio.h>
int main(void)
{
int x = 10;
while( --x> 0 ) // x goes to 0
{
printf("%d ", x);
}
return 0;
}
That output is:
9 8 7 6 5 4 3 2 1
My compiler will print out 9876543210 when I run this code.
#include <iostream>
int main()
{
int x = 10;
while( x --> 0 ) // x goes to 0
{
std::cout << x;
}
}
As expected. The while( x-- > 0 ) actually means while( x > 0). The x-- post decrements x.
while( x > 0 )
{
x--;
std::cout << x;
}
is a different way of writing the same thing.
It is nice that the original looks like "while x goes to 0" though.
There is a space missing between -- and >. x is post decremented, that is, decremented after checking the condition x>0 ?.
-- is the decrement operator and > is the greater-than operator.
The two operators are applied as a single one like -->.
It's a combination of two operators. First -- is for decrementing the value, and > is for checking whether the value is greater than the right-hand operand.
#include<stdio.h>
int main()
{
int x = 10;
while (x-- > 0)
printf("%d ",x);
return 0;
}
The output will be:
9 8 7 6 5 4 3 2 1 0
C and C++ obey the "maximal munch" rule. The same way a---b is translated to (a--) - b, in your case x-->0 translates to (x--)>0.
What the rule says essentially is that going left to right, expressions are formed by taking the maximum of characters which will form a valid token.
Actually, x is post-decrementing and with that condition is being checked. It's not -->, it's (x--) > 0
Note: value of x is changed after the condition is checked, because it post-decrementing. Some similar cases can also occur, for example:
--> x-->0
++> x++>0
-->= x-->=0
++>= x++>=0
char sep = '\n' /1\
; int i = 68 /1 \
; while (i --- 1\
\
/1/1/1 /1\
/1\
/1\
/1\
/1\
/ 1\
/ 1 \
/ 1 \
/ 1 \
/1 /1 \
/1 /1 \
/1 /1 /1/1> 0) std::cout \
<<i<< sep;
For larger numbers, C++20 introduces some more advanced looping features.
First to catch i we can build an inverse loop-de-loop and deflect it onto the std::ostream. However, the speed of i is implementation-defined, so we can use the new C++20 speed operator <<i<< to speed it up. We must also catch it by building wall, if we don't, i leaves the scope and de referencing it causes undefined behavior. To specify the separator, we can use:
std::cout \
sep
and there we have a for loop from 67 to 1.
Instead of regular arrow operator (-->) you can use armor-piercing arrow operator: --x> (note those sharp barbs on the arrow tip). It adds +1 to armor piercing, so it finishes the loop 1 iteration faster than regular arrow operator. Try it yourself:
int x = 10;
while( --x> 0 )
printf("%d ", x);
Why all the complication?
The simple answer to the original question is just:
#include <stdio.h>
int main()
{
int x = 10;
while (x > 0)
{
printf("%d ", x);
x = x-1;
}
}
It does the same thing. I am not saying you should do it like this, but it does the same thing and would have answered the question in one post.
The x-- is just shorthand for the above, and > is just a normal greater-than operator. No big mystery!
There are too many people making simple things complicated nowadays ;)
Conventional way we define condition in while loop parenthesis"()" and terminating condition inside the braces"{}", but this -- & > is a way one defines all at once.
For example:
int abc(){
int a = 5
while((a--) > 0){ // Decrement and comparison both at once
// Code
}
}
It says, decrement a and run the loop till the time a is greater than 0
Other way it should have been like:
int abc() {
int a = 5;
while(a > 0) {
a = a -1 // Decrement inside loop
// Code
}
}
Both ways, we do the same thing and achieve the same goals.
(x --> 0) means (x-- > 0).
You can use (x -->)
Output: 9 8 7 6 5 4 3 2 1 0
You can use (-- x > 0) It's mean (--x > 0)
Output: 9 8 7 6 5 4 3 2 1
You can use
(--\
\
x > 0)
Output: 9 8 7 6 5 4 3 2 1
You can use
(\
\
x --> 0)
Output: 9 8 7 6 5 4 3 2 1 0
You can use
(\
\
x --> 0
\
\
)
Output: 9 8 7 6 5 4 3 2 1 0
You can use also
(
x
-->
0
)
Output: 9 8 7 6 5 4 3 2 1 0
Likewise, you can try lot of methods to execute this command successfully.
This --> is not an operator at all. We have an operator like ->, but not like -->. It is just a wrong interpretation of while(x-- >0) which simply means x has the post decrement operator and this loop will run till it is greater than zero.
Another simple way of writing this code would be while(x--). The while loop will stop whenever it gets a false condition and here there is only one case, i.e., 0. So it will stop when the x value is decremented to zero.
Here -- is the unary post decrement operator.
while (x-- > 0) // x goes to 0
{
printf("%d ", x);
}
In the beginning, the condition will evaluate as
(x > 0) // 10 > 0
Now because the condition is true, it will go into the loop with a decremented value
x-- // x = 9
That's why the first printed value is 9
And so on. In the last loop x=1, so the condition is true. As per the unary operator, the value changed to x = 0 at the time of print.
Now, x = 0, which evaluates the condition (x > 0 ) as false and the while loop exits.
--> is not an operator, it is the juxtaposition of -- (post-decrement) and > (greater than comparison).
The loop will look more familiar as:
#include <stdio.h>
int main() {
int x = 10;
while (x-- > 0) { // x goes to 0
printf("%d ", x);
}
}
This loop is a classic idiom to enumerate values between 10 (the excluded upper bound) and 0 the included lower bound, useful to iterate over the elements of an array from the last to the first.
The initial value 10 is the total number of iterations (for example the length of the array), and one plus the first value used inside the loop. The 0 is the last value of x inside the loop, hence the comment x goes to 0.
Note that the value of x after the loop completes is -1.
Note also that this loop will operate the same way if x has an unsigned type such as size_t, which is a strong advantage over the naive alternative for (i = length-1; i >= 0; i--).
For this reason, I am actually a fan of this surprising syntax: while (x --> 0). I find this idiom eye-catching and elegant, just like for (;;) vs: while (1) (which looks confusingly similar to while (l)). It also works in other languages whose syntax is inspired by C: C++, Objective-C, java, javascript, C# to name a few.
That's what you mean.
while((x--) > 0)
We heard in childhood,
Stop don't, Let Go (روکو مت، جانے دو)
Where a Comma makes confusion
Stop, don't let go. (روکو، مت جانے دو)
Same Happens in Programming now, a SPACE makes confusion. :D
The operator you use is called "decrement-and-then-test". It is defined in the C99 standard, which is the latest version of the C programming language standard. The C99 standard added a number of new operators, including the "decrement-and-then-test" operator, to the C language. Many C++ compilers have adopted these new operators as extensions to the C++ language.
Here is how the code without using the "decrement-and-then-test" operator:
#include <stdio.h>
int main()
{
int x = 10;
while (x > 0)
{
printf("%d ", x);
x--;
}
}
In this version of the code, the while loop uses the > operator to test whether x is greater than 0. The x-- statement is used to decrement x by 1 at the end of each iteration of the loop.