IF-nesting in c++ - c++

heyall, just going through some textbook examples for my introductory c++ course and I would really appreciate it if somebody could clarify why the following code produces an output of 51 (I would expect it to not produce any output whatsoever), many thanks!:
#include <iostream>
using namespace std;
int main()
{
constexpr int a{9};
constexpr int b{1};
constexpr int c{5};
if (a < b < c)
if (c > b > a)
if (a > c) cout << 91;
else cout << 19;
else
if (b < c) cout << 51;
else cout << 15;
else
if (b < a < c)
if (a < c) cout << 95;
else cout << 59;
else
if (b < c) cout << 57;
else cout << 75;
return 0;
}

It seems you expect this expression:
if (a < b < c)
to be true if a, b, and c are in increasing order. But what actually happens is the expression becomes:
if ((a < b) < c)
which is either:
if (0 < c)
// or
if (1 < c)
Either way, that's probably not what you want. In fact, there's no good reason to ever write the above expression.
If you want to check whether the variables are increasing, you need to write something like:
if (a < b && b < c)

In c++, comparisons like 'X<=Y<=Z' do not have their mathematical meaning without parentheses. So, in
if (a < b < c)
we are getting
a < b => 9 < 1 => 0
'0' means the condition is false, which with 'c' is returning
0 < 5 => 1
"1" being returned means that the if condition is True.
Similarly, you can check for the nested if-else loops.

Related

there is a question to find middle number . i tried really hard [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed yesterday.
Improve this question
I need to find middle number from 3 numbers the user inputs. I'm completely new to C++.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a, b, c, d, mdq, mnq, mxq, mdw, mnw, mxw, mde, mne, mxe;
cin>>a>>b>>c;
mda = c;
if (mda>a and mda<b) mdq = c;
if (mda>a and mda>b) mxa = c;
if (mdq<a and mdq<b) mnq = c;
mdw = a:
if (mdw>b and mdw<c) mdq = a;
if (mdw>b and mdw>c) mxg = a;
if (mdw<b and mdw<c) mnq = a;
mde = b;
if (mde>a and mde<c) mdq = b;
if (mde>a and mde>c) mxq = b;
if (mde<a and mde<c) mnq = b;
d = mdq+mxq+mng:
d = d-mxq-mnq;
cout<<d;
}
I tried to find middle number and it sometimes work but whenever i type 4 7 1 the output is 1.
I think you are trying far too hard. There are only six possibilities, you don't need complicated logic and you definitely don't need mathematics.
#include <iostream>
int main()
{
int a, b, c;
std::cin >> a >> b >> c;
// it's a if b <= a <= c OR c <= a <= b
if ((b <= a && a <= c) || (c <= a && a <= b))
std::cout << "first # " << a << '\n';
// it's b if a <= b <= c OR c <= b <= a
else if ((a <= b && b <= c) || (c <= b && b <= a))
std::cout << "second # " << b << '\n';
// neither of the above, must be c
else
std::cout << "third # " << c << '\n';
}
I suppose the only tricky part is how to deal with equal numbers. I used <= which means given equal numbers the earlier number will be printed. So for example given 11 22 22 the output is second # 22 not third # 22.
Consider:
#include <algorithm>
#include <iostream>
int main()
{
int a, b, c ;
std::cin >> a >> b >> c ;
if( a > b ) std::swap( a, b ) ;
if( b > c ) std::swap( b, c ) ;
if( a > b ) std::swap( a, b ) ;
std::cout << b << '\n' ;
return 0;
}
It sorts the three values in order so that the answer is always b.
An alternative that does not modify the input:
#include <algorithm>
#include <iostream>
int main()
{
int a, b, c ;
std::cin >> a >> b >> c ;
int max1 = std::max( a, b ) ;
int max2 = std::max( b, c ) ;
int max3 = std::max( a, c ) ;
int mid = std::min( max1, max2 ) ;
mid = std::min( mid, max3 ) ;
std::cout << mid << '\n' ;
return 0;
}
which uses just four additional variables rather than ten in your attempt. It works by determining the maximum of all possible pairs: a,b, b,c and a,c, giving three values that contain either the largest or second largest value - the second largest value of three is also the middle value of course, so the smaller of these three maxima is the middle value.
You need not rely on the min()/max() functions here - they can be replaced with for example the expressions a < b ? a : b ; and a > b ? a : b or even if( a > b ) max1 = a; else max1 = b; etc.
Perhaps a more obvious solution, given that there are only 6 possible orderings of a b c, and only three possible outcomes for the middle value, then you can explicitly test for each possibility. You only need to explicitly test for two possible outcomes, since if neither of those are true, the answer is the third possibility:
#include <iostream>
int main()
{
int a, b, c;
std::cin >> a >> b >> c ;
int mid = a ; // Initially assume a is the middle
// (i.e. order: b a c or c a b)
// If b is in the middle...
if( (a <= b && b <= c) || // a b c or...
(c <= b && b <= a) ) // c b a
{
mid = b ;
}
// else if c is in the middle
else if( (a <= c && c <= b) || // a c b or...
(b <= c && c <= a) ) // b c a
{
mid = c ;
}
std::cout << mid << '\n' ;
return 0 ;
}
This is essentially #john's solution (credit), but you may find the explanatory comments here easier to follow perhaps.

Unordered selection implementation based on std::set ends up having duplicates

Trying to implement a combination of 4 objects taken 2 at a time without taking into account the arrangement (such must be considered duplicates: so that order is not important) of objects with std::set container:
struct Combination {
int m;
int n;
Combination(const int m, const int n):m(m),n(n){}
};
const auto operator<(const auto & a, const auto & b) {
//explicitly "telling" that order should not matter:
if ( a.m == b.n && a.n == b.m ) return false;
//the case "a.m == b.m && a.n == b.n" will result in false here too:
return a.m == b.m ? a.n < b.n : a.m < b.m;
}
#include <set>
#include <iostream>
int main() {
std::set< Combination > c;
for ( short m = 0; m < 4; ++ m ) {
for ( short n = 0; n < 4; ++ n ) {
if ( n == m ) continue;
c.emplace( m, n );
} }
std::cout << c.size() << std::endl; //12 (but must be 6)
}
The expected set of combinations is 0 1, 0 2, 0 3, 1 2, 1 3, 2 3 which is 6 of those, but resulting c.size() == 12. Also, my operator<(Combination,Combination) does satisfy !comp(a, b) && !comp(b, a) means elements are equal requirement.
What am I missing?
Your code can't work1, because your operator< does not introduce a strict total ordering. One requirement for a strict total ordering is that, for any three elements a, b and c
a < b
and
b < c
imply that
a < c
(in a mathematical sense). Let's check that. If we take
Combination a(1, 3);
Combination b(1, 4);
Combination c(3, 1);
you see that
a < b => true
b < c => true
but
a < c => false
If you can't order the elements you can't use std::set. A std::unordered_set seems to more suited for the task. You just need a operator== to compare for equality, which is trivial and a hash function that returns the same value for elements that are considere identical. It could be as simple as adding m and n.
1 Well, maybe it could work, or not, or both, it's undefined behaviour.
Attached is the working code. The tricky part that you were missing was not adding a section of code to iterate through the already working set to then check the values. You were close! If you need a more thorough answer I will answer questions in the comments. Hope this helps!
#include <set>
#include <iostream>
using namespace std;
struct Combination {
int m;
int n;
Combination(const int m, const int n):m(m),n(n){}
};
const auto operator<(const auto & a, const auto & b) {
//explicitly "telling" that order should not matter:
if ( a.m == b.n && a.n == b.m ) return false;
//the case "a.m == b.m && a.n == b.n" will result in false here too:
return a.m == b.m ? a.n < b.n : a.m < b.m;
}
int main() {
set< Combination > c;
for ( short m = 0; m < 4; ++ m )
{
for ( short n = 0; n < 4; ++ n )
{
//Values are the same we do not add to the set
if(m == n){
continue;
}
else{
Combination s(n,m);
const bool is_in = c.find(s) != c.end();
if(is_in == true){
continue;
}
else{
cout << " M: " << m << " N: " << n << endl;
c.emplace( m, n);
}
}
}
}
cout << c.size() << endl; //16 (but must be 6)
}

Finding MAX of numbers without conditional IF statements c++ [duplicate]

This question already has answers here:
Mathematically Find Max Value without Conditional Comparison
(18 answers)
Closed 9 years ago.
So i have too get two numbers from user input, and find the max of the two numbers without using if statements.
The class is a beginner class, and we have too use what we already know. I kinda worked something out, but it only works if the numbers are inputted with the max number first.
#include <iostream>
using namespace std;
int main()
{
int x = 0, y = 0, max = 0;
int smallest, largest;
cout << "Please enter 2 integer numbers, and i will show you which one is larger: ";
cin >> x >> y;
smallest = (x < y == 1) + (x - 1);
smallest = (y < x == 1) + (y - 1);
largest = (x < y == 1) + (y - 1);
largest = (y > x == 1) + (x + 1 - 1);
cout << "Smallest: " << smallest << endl;
cout << "Largest: " << largest << endl;
return 0;
}
Thats what i have so far, but after putting different test data in, i found out it only works for numbers such as 4,5 or 6,7. But numbers with more then 2 spaces between eachother they dont such as, 4,8 or 5, 7. Any help would be appreciated.
I saw this question in Cracking the Coding interview book.
Let’s try to solve this by “re-wording” the problem We will re-word the problem until we get something that has removed all if statements
Rewording 1: If a > b, return a; else, return b
Rewording 2: If (a - b) is negative, return b; else, return a
Rewording 3: If (a - b) is negative, let k = 1; else, let k = 0 Return a - k * (a - b)
Rewording 4: Let c = a - b Let k = the most significant bit of c Return a - k * c
int getMax(int a, int b) {
int c = a - b;
int k = (c >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1;
int max = a - k * c;
return max;
}
Source: http://www.amazon.com/Cracking-Coding-Interview-Programming-Questions/dp/098478280X
Edit: This code works even when a-b overflows.
Let k equal the sign of a-b such that if a-b >=0, then k is 1, else k=0.Let q be the inverse of k. Above code overflows when a is positive or b is negative, or the other way around. If a and b have different signs, then we want the k to equal sign(a).
/* Flips 1 to 0 and vice-versa */
public static int flip(int bit){
return 1^bit;
}
/* returns 1 if a is positive, and 0 if a is negative */
public static int sign(int a){
return flip((a >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1);
}
public static int getMax(int a, int b){
int c = a - b;
int sa = sign(a-b); // if a>=0, then 1 else 0
int sb = sign(a-b); // if b>=1, then 1 else 0
int sc = sign(c); // depends on whether or not a-b overflows
/* If a and b have different signs, then k = sign(a) */
int use_sign_of_a = sa ^ sb;
/* If a and b have the same sign, then k = sign(a - b) */
int use_sign_of_c = flip(sa ^ sb);
int k = use_sign_of_a * sa + use_sign_of_c * sc;
int q = flip(k); //opposite of k
return a * k + b * q;
}
Here is a funny solution:
int max_num = (x>y)*x + (y>=x)*y;
Assuming that you have covered bitwise operators already you can do this:
max = a-((a-b)&((a-b)>>(sizeof(int)*8-1)));
This is based off of the solution from Mathematically Find Max Value without Conditional Comparison that #user93353 pointed out in the comments above.
This may be overkill if you really are just trying to avoid if statements, not comparisons in general.
You can try this code to find max and min for two input variables.
((a > b) && (max = a)) || (max=b);
((a < b) && (min = a)) || (min=b);
For three input variables you can use similar method like this:
int main()
{
int a = 10, b = 9 , c = 8;
cin >> a >> b >> c;
int max = a, min = a;
// For Max
((a > b) && (a > c) && (max=a)) ||
((b > c) && (b > a) && (max=b)) ||
(max=c) ;
// For min
((a < b) && (a < c) && (min=a)) ||
((b < c) && (b < a) && (min=b)) ||
(min=c) ;
cout << "max = " << max;
cout << "and min = " << min;
return 1;
}
One run is:
:~$ ./a.out
1
2
3
max = 3 and min = 1
Edit
Thanks to #Tony D: This code will fail for negative numbers.
One may try this for negative numbers for two inputs to find max(not sure for this):
((a > b) && ( a > 0 && (max = a))) || ((b > a) && (max = b)) || (max = a);

How can I write a for loop with (a < b < c) under one statement?

I'm trying to do a for loop that looks like this.
int a = 3;
int b;
int c = 20;
for ( a = 1; a < b < c; ++a )
But the program doesn't work like this. How am i suppose to correctly state that stament in the middle a < b < c?
Change a < b < c to a < b && b < c
Explanation
The reason is that, < is evaluated from left-to-right, so your statement is evaluated like this:
a < b < c --> (a < b) < c
(a < b) is a boolean value (0 or 1) and c is being compared to that value.
If you have both a < b and b < c, since < is transitive, you would know that the mathematical a < b < c holds.
Note: Taking a look at the C operator precedence table, you can see that in the expression a < b && b < c, first a < b and b < c are evaluated, then the results are "and"ed.
Your example
In your example, since b is not set, a < b is not known, but whether it is 0 or 1, it is definitely smaller than c which is 20. So basically you've got an infinite loop.

Why does the answer print out twice?

I made a program that returns the product abc where a,b,c are pythagorean triples and add up to 1000. The program does output the correct answer but does it twice. I was curious as to why this is so. After playing around with it a bit I found out that it prints out when a = 200 b = 375 c = 425. And once again when a = 375 b = 200 c = 425.
bool isPythagTriple(int a, int b, int c);
int main()
{
for(int a = 1; a < 1000; a++)
{
for(int b = 1; b < 1000; b++)
{
for(int c = 1; c < 1000; c++)
{
if( ((a+b+c)==1000) && isPythagTriple(a,b,c) )
{
cout << a*b*c << " ";
break;
}
}
}
}
return 0;
}
bool isPythagTriple(int a, int b, int c)
{
if( (a*a)+(b*b)-(c*c) == 0 )
return true;
else
return false;
}
Just for what it's worth, I'd write this function:
bool isPythagTriple(int a, int b, int c)
{
if( (a*a)+(b*b)-(c*c) == 0 )
return true;
else
return false;
}
More like this:
bool isPythagTriple(int a, int b, int c) {
return a*a+b*b==c*c;
}
Break, in this case, will only break out of the c loop, not the b and a ones.
A quick fix is to ensure you don't get repeats by starting each variable greater than or equal to the previous (so b is never less than a and c is never less than b).
In addition, you can actually get rid of the c loop altogether since there's only one value of c that is valid for a given a,b pair (unless a + b + c > 1000 in which case there are none). I would try something like:
for (int a = 1; a < 1000; a++) {
for (int b = a; b < 1000; b++) {
int c = 1000 - a - b;
if (c >= b) {
if (isPythagTriple (a,b,c)) {
cout << a << " " << b << " " << c << " " << a*b*c << std::endl;
}
}
}
}
The overall effect of that is to reduce the total loop count from a billion (short scale) to about half a million hence reducing it by about 99.95% - that should be a tiny bit faster :-)
And potentially making it faster with Jerry Coffin's suggestion as well (and an inline suggestion to the compiler), a full program:
#include <iostream>
inline bool isPythagTriple(int a, int b, int c) {
return a * a + b * b == c * c;
}
int main() {
for(int a = 1; a < 1000; a++) {
for(int b = a; b < 1000; b++) {
int c = 1000 - a - b;
if (c >= b) {
if (isPythagTriple(a,b,c)) {
std::cout << a << " " << b << " " << c << " "
<< a*b*c << std::endl;
}
}
}
}
return 0;
}
which takes 0.004 seconds on average (system + user) on my box, with the original taking about 2.772 seconds on average (ten samples each). Not that it really matters unless you're running it many, many times, of course.
The output of that code is, as expected:
200 375 425 31875000
This is how break and continue work - break only exits the inner-most loop. Read the discussion on this question for some alternatives to this.
The reason this happens is because you only break out of the inner loop (for c). The outer loops carry on running and re-enter the inner loop, meeting the conditions again. There are numerous values that add to 1000 and you are catching some of them - you have caught 2, as your print indicates. You could use "return" instead of break if you want only the first combination of values output.
As for the "code block" I am not sure what you mean.. You already seem to know to write functions. If what you mean is a scope block, then you simply enclose the code of concern in curly braces -> { }
E.g.
{
int i = 0;
i++;
}
To prevent multiple orderings of the solutions, make sure that c >= b >= a. You can do this by changing the lower bounds:
for(int a = 1; a < 1000; a++) {
for(int b = a; b < 1000; b++) {
for(int c = b; c < 1000; c++) {