Time class comparison - c++

bool operator < (Time obj_a, Time obj_b)
{
return ((obj_a.hours<=obj_b.hours || obj_a.minutes<=obj_b.minutes) &&
(obj_a.hours<=obj_b.hours || obj_a.minutes<=obj_b.minutes));
}
bool operator > (Time obj_a, Time obj_b)
{
return (obj_a.hours>=obj_b.hours || obj_a.minutes>=obj_b.minutes);
}
bool operator == (Time obj_a, Time obj_b)
{
return (obj_a.hours==obj_b.hours && obj_a.minutes==obj_b.minutes);
}
Can somebody tell me whats wrong with these operators.They are comparing time of hours and minutes.but i am not getting correct comparison.I have defined a class of Time in which hours and minutes are stored.

There's a lot wrong with this code. First off, you're reducing < comparisons to <= comparisons, which (if the rest of your logic were correct) would mean that equal times would compare either < or >, depending on the order of arguments to the comparison routines.
Then,
((obj_a.hours<=obj_b.hours || obj_a.minutes<=obj_b.minutes) &&
(obj_a.hours<=obj_b.hours || obj_a.minutes<=obj_b.minutes))
performs exactly the same comparison twice in an &&, so it's actually doing just
obj_a.hours<=obj_b.hours || obj_a.minutes<=obj_b.minutes
This doesn't work because it wants either the hours, or the minutes to be <=. That means 11:30 <= 10:40 because 30 <= 40.
The easiest way to tackle this problem is to reduce your comparisons on time objects to comparisons on minutes only, e.g.
a.hours * 60 + a.minutes < b.hours * 60 + b.minutes

Related

Why will my elseif statment never executed

Any idea why the else if statment will be never executed ? The value of difference is constantly changing when the program runs.
double difference = abs(reale_x[0] - reale_x[1]);
if (0 <= difference < 45) {
timer_counter += 1;
if (timer_counter == 30) {
cout << "CLICK" << '\n';
}
}
else if (difference > 50) {
timer_counter = 0;
}
That is not how comparation works in c++.
What this code
if (0 <= difference < 45) {
does is it first compares if 0 is smaller or equal to difference. It is then "replaced" by a bool value either true or false. And then a bool value (so either 1 or 0) is compared to 45. And it will always be smaller than 45. What you have there is an always true statement.
So the way you would write this if statement is
if (difference >= 0 && difference < 45){
Note that because of your else if statement it will not execute if the difference is >44 and <51
if (0 <= difference < 45) will be executed as if ((0 <= difference) < 45), which will be either 0<45 or 1<45 and will always be true. That's why the else part is not getting executed.
in mathematics, we see and write 0 <= x < 45 or something like that to define the range of the variable x. But in order to tell the computer the same thing, you have to tell more clearly. Saying, to have to tell the compiler, that the value of x is greater than or equal to zero and at the same time, that value will be less than 45, and you can tell the compiler by this statement: difference >= && difference < 45 . the && is an 'AND' operator in most of the languages.

Using if statement to satisfy two conditions

I'm coding a simple shoot-a-cannon-ball 'game' for my class and I have to have the program print "HIT" when it hits the target. The code I am using is (h being the y axis and d being the x axis):
if (h > 100 && 680<d<780)
{
write_string("HIT");
}
However it will print "HIT" even if just one of these conditions is satisfied. How do I make it so BOTH of these conditions have to be satisfied before it will perform the operation?
If I need to post more code for context I can.
The expression 680<d<780 doesn't do what you think it does.
It first checks if 680<d, which then gets evaluated to true or false.
This resulting expression is then compared to see if it is less than 780, meaning that you could get the condition true < 780 or false < 780 (Both of which are true, since true == 1 and false == 0).
You probably meant 680<d && d<780, which checks if d is in the range from 680 to 780 through a boolean AND condition.
if (h > 100 && 680 < d && d < 780) {
write_string("HIT");
}
You can only do one less than comparison at a time. Do them separately and check are they both true using '&&' operator.
That is because < is a binary operator, and as a result, your expression gets evaluated in ways that you didn't want.
Checking the operator precedence tables, it seems your expression is getting evaluated as (h > 100 && (680 < d) < 780), in which case it is true independent of the value of d (because (680 < d) = true will result in 1 < 780 and (680 < d) = false will result in 0 < 780). But the value of h should affect still.
Anyway, you have to rewrite your if condition as (h > 100 && 680 < d && d < 780).

Is condition evaluation optimized ? Is this code bad?

1.Imagine condition if (obj.is_x() || obj.is_y() || obj.is_z())
Will obj.is_y() and obj.is_z() be called and evaluated if obj.is_x() returned true ?
2.Is this a bad idea(in general)? Does this code look bad ?
bool isbn13_prefix_valid (const string& prefix)
{
unsigned num = stoi(prefix);
if (num == 978 || num == 979) return 1; //super common ones
else if ( num >= 0 && num <= 5 || num == 7 || num >= 600 && num <= 649
|| num >= 80 && num <= 94 || num >= 950 && num <= 989
|| num >= 9900 && num <= 9989 || num >= 99900 && num <= 99999)
return 1;
return 0;
}
No, it will not, due to short-circuiting.
Yes, that code looks bad. Not because it's incorrect, but because you're stuffing an extremely long conditional into a single if statement. Try refactoring your code to make it cleaner.
Your code is absolutely fine. I'd like to see a comment where these strange numbers come from, that's all.
Turning it into a dozen trivial functions as has been suggested is in no way helpful. It actually makes it a lot harder to read the code, because it gets spread out over many many lines of code. Yes, it is complex. But that's due to the problem being complex, and trying to spread the complexity out doesn't help one bit.
Your actual question: In a || b, a is evaluated first. If it is true, then b is not evaluated and the result is true. If a is false, then b is also evaluated and the result is true or false, depending on the result of b.
An optimising compiler may start evaluating b before it has finished evaluating a, if it can prove that the evaluation of b has no side effects, and if it believes that (mostly due to parallelism in the hardware) it is on average faster to evaluate as much in parallel as possible, even if some things are evaluated when it wasn't necessary. But this is not noticable in the results of your code, and will only make the code faster.

C++ random numbers logical operator wierd outcome

I am trying to make a program generating random numbers until it finds a predefined set of numbers (eg. if I had a set of my 5 favourite numbers, how many times would I need to play for the computer to randomly find the same numbers). I have written a simple program but don't understand the outcome which seems to be slightly unrelated to what I expected, for example the outcome does not necessarily contain all of the predefined numbers sometimes it does (and even that doesn't stop the loop from running). I think that the problem lies in the logical operator '&&' but am not sure. Here is the code:
const int one = 1;
const int two = 2;
const int three = 3;
using namespace std;
int main()
{
int first, second, third;
int i = 0;
time_t seconds;
time(&seconds);
srand ((unsigned int) seconds);
do
{
first = rand() % 10 + 1;
second = rand() % 10 + 1;
third = rand() % 10 + 1;
i++;
cout << first<<","<<second<<","<<third<< endl;
cout <<i<<endl;
} while (first != one && second != two && third != three);
return 0;
}
and here is out of the possible outcomes:
3,10,4
1 // itineration variable
7,10,4
2
4,4,6
3
3,5,6
4
7,1,8
5
5,4,2
6
2,5,7
7
2,4,7
8
8,4,9
9
7,4,4
10
8,6,5
11
3,2,7
12
I have also noticed that If I use the || operator instead of && the loop will execute until it finds the exact numbers respecting the order in which the variables were set (here: 1,2,3). This is better however what shall I do make the loop stop even if the order is not the same, only the numbers? Thanks for your answers and help.
The issue is here in your condition:
} while (first != one && second != two && third != three);
You continue while none of them is equal. But once at least one of them is equal, you stop/leave the loop.
To fix this, use logical or (||) rather than a logical and (&&) to link the tests:
} while (first != one || second != two || third != three);
Now it will continue as long as any of them doesn't match.
Edit - for a more advanced comparison:
I'll be using a simple macro to make it easier to read:
#define isoneof(x,a,b,c) ((x) == (a) || (x) == (b) || (x) == (c))
Note that there are different approaches you could use.
} while(!isoneof(first, one, two, three) || !isoneof(second, one, two, three) || !isoneof(third, one, two, three))
You have a mistake in your logical condition: it means "while all numbers are not equal". To break this condition, it is enough for one pair to become equal.
You needed to construct a different condition - either put "not" in front of it
!(first==one && second==two && third==three)
or convert using De Morgan's law:
first!=one || second!=two || third!=three

Chaining Bool values give opposite result to expected

Unthinkingly I wrote some code to check that all the values of a struct were set to 0. To accomplish this I used:
bool IsValid() {
return !(0 == year == month == day == hour == minute == second);
}
where all struct members were of type unsigned short. I used the code as part of a larger test but noticed that it was returning false for values differing from zero, and true for values that were all equal to zero - the opposite of what I expected.
I changed the code to read:
bool IsValid() {
return (0 != year) || (0 != month) || (0 != day) || (0 != hour) || (0 != minute) || (0 != second);
}
But would like to know what caused the odd behaviour. Is it a result of precedence? I've tried to Google this answer but found nothing, if there's any nomenclature to describe the result I'd love to know it.
I compiled the code using VS9 and VS8.
== groups from left to right, so if all values are zero then:
0 == year // true
(0 == year) == month // false, since month is 0 and (0 == year) converts to 1
((0 == year) == month) == day // true
And so on.
In general, x == y == z is not equivalent to x == y && x == z as you seem to expect.
The behaviour shouldn't be seen as odd. The grammar rules for == (and most but not all binary operators) specify left to right grouping so your original expression is equivalent to:
!((((((0 == year) == month) == day) == hour) == minute) == second)
Note that when compared to an integer type a bool expression with value true will promote to 1 and with value false will promote to 0. (In C the result of the equality operator is an int in any case with a value or either 1 or 0.)
This means that, for example, ((0 == year) == month) will be true if year is zero and month is one or if year is non-zero but month is zero and false otherwise.
You have to consider how it's evaluated...
a == b == c
is asking if two of them are equal (a and b), then comparing that boolean result to the third value c! It is NOT comparing the first two values with the third. Anything beyond 2 arguments won't chain as you evidently expect.
For whatever it's worth, because C++ considers non-0 values to be "true" in a boolean context, you can express what you want simply as:
return year && month && day && hour && minute && second;
(note: your revised code says "month" twice and doesn't test minute).
Back to the chained ==s: with user-defined types and operator overloading you can create a class that compares as you expect (and it can even allow things like 0 <= x < 10 to "work" in the way it's read in mathematics), but creating something special will just confuse other programmers who already know the (weird) way these things work for builtin types in C++. Worth doing as a ten/twenty minute programming exercise though if you're keen to learn C++ in depth (hint: you need the comparison operators to return a proxy object that remembers what will be the left-hand-side value for the next comparison operator).
Finally, sometimes these "weird" boolean expressions are useful: for example, a == b == (c == d) might be phrased in English as "either (a == b) and (c == d), OR (a != b) and (c != d)", or perhaps "the equivalence of a and b is the same as the equivalence of c and d (whether true or false doesn't matter)". That might model real world situations like a double-dating scenario: if a likes/dislikes b (their date) as much as c likes/dislikes d, then they'll either hang around and have a nice time or call it quits quickly and it's painless either way... otherwise one couple will have a very tedious time of it.... Because these things can make sense, it's impossible for the compiler to know you didn't intend to create such an expression.
Your error here is writing a mathematical expression using equals signs, and unthinkingly supposing that the computer will perform the test you meant - what a human mathematician would see as the meaning of those symbols. What the computer does (as per the definition of the language) is to perform a series of discrete comparisons, each of which returns true or false - and this true or false is then used in the next comparison. You aren't comparing all of those variables to 0, you're comparing each (bar two of them) to the result of comparing another two of the said variables.
The return of the == operator is 1 if the operands are equal, so regardless wether this is read from left to right or right to left, this will not do what you expect.
so this could only work in an analogous test if you would be interested if all values are 1.
And to have a shorter expression since you seem interested in that just do year || day || ...