-
December 17th, 2008, 01:05 AM
#1
math logic confusion
This should be simple, but I can't seem to figure out a logic behind this without hard coding tons of nested ifs, there's got to be a simple way.
Say I got a class with these members:
long int m_seconds;
long int m_minutes;
long int m_hours;
long int m_days;
I have two instances of this class, and I want to check if one of them is bigger then the other based on those values treated as time. I started coding it and got into a huge mess of if nests several levels deep. There must be a simpler way right?
-
December 17th, 2008, 01:19 AM
#2
Re: math logic confusion
Well, if you wanted to use no if statements at all you could go with something like:
Code:
bool operator<(const DateTime& lhs, const DateTime& rhs)
{
return lhs.m_days < rhs.m_days
|| (lhs.m_days == rhs.m_days
&& (lhs.m_hours < rhs.m_hours
|| (lhs.m_hours == rhs.m_hours
&& (lhs.m_minutes < rhs.m_minutes
|| (lhs.m_minutes == rhs.m_minutes
&& lhs.m_seconds < rhs.m_seconds)))));
}
But I am not sure if this would be obfuscation or clarification: on one hand, the pattern should be easy to discern, but on the other hand, you have quite a few nested parentheses that the structure does not clearly show.
-
December 17th, 2008, 01:21 AM
#3
Re: math logic confusion
Ah ok I was on right track, is there any speed difference or does compiler optimize it anyway?
This is what I have:
Code:
bool TimeSpan::operator>(const TimeSpan &other) const
{
if(m_days>other.m_days)return true;
else if(m_days<other.m_days)return false;
//at this point days are equal
if(m_hours>other.m_hours)return true;
else if(m_hours<other.m_hours)return false;
//at this point hours are equal
if(m_minutes>other.m_minutes)return true;
else if(m_minutes<other.m_minutes)return false;
//at this point hours are equal
if(m_seconds>other.m_seconds)return true;
else if(m_seconds<other.m_seconds)return false;
//at this point seconds are equal, we return false since we want > and not =>
return false;
}
My >= operator checks against == followed by => so I'm not repeating code.
-
December 17th, 2008, 01:34 AM
#4
Re: math logic confusion
Originally Posted by Red Squirrel
Ah ok I was on right track, is there any speed difference or does compiler optimize it anyway?
I doubt that it would make a difference either way once compiler does its optimisation. If this is a bottleneck you could always measure and see if one is faster than the other.
Originally Posted by Red Squirrel
My >= operator checks against == followed by => so I'm not repeating code.
It is more canonical to implement operator< instead of operator> since operator< is the one used by the standard generic algorithms by default. You do not actually need to use operator== to implement operator<= or operator>=. The trick is that with operator<, (a > b) == (b < a), (a <= b) == !(b < a), (a >= b) == !(a < b).
In fact, by defining operator== and operator<, you can just #include <utility> and then do a using namespace std::rel_ops to get the other four (including operator!=).
-
December 17th, 2008, 06:02 AM
#5
Re: math logic confusion
Originally Posted by Red Squirrel
Ah ok I was on right track,
I agree with laserlight -- overload operator < and operator == first, then write the other operators in terms of these operators. Writing a full-blown operator > seems to be a mistake (it would be where I work)-- you should spend the time writing operator < and operator ==. The other operators can then be written (using either laserlight's recommendation or with simple one-line functions) once < and == are implemented
The < and == operators are used throughout the C++ algorithms (i.e. the term strict weak ordering is used in the definition of many algorithms, meaning operator <.)
Regards,
Paul McKenzie
-
December 17th, 2008, 07:48 AM
#6
Re: math logic confusion
Code:
(a <= b) == !(b < a), (a >= b) == !(a < b).
Great explanation.
Thanks for your help.
-
December 17th, 2008, 08:14 AM
#7
Re: math logic confusion
Another approach would be to convert each to the total number of seconds and just compare the two numbers. That would be logically simpler.
-
December 17th, 2008, 08:27 AM
#8
Re: math logic confusion
Originally Posted by Paul McKenzie
the term strict weak ordering is used in the definition of many algorithms, meaning operator <
ok, but in that case the operator < must satisfy strict weak ordering axioms. Suppose you want to define, say, a simple partial order; in your opinion, what's the best practice ? defining only the operator <= or defining a (non-)member function ?
-
December 17th, 2008, 08:56 AM
#9
Re: math logic confusion
The rule of thumb is that you shouldn't use an operator in a way inconsistent with how the integers would use it. So for any "unusual" relations, use a named function.
Besides, for a partial ordering you need three results: true, false, and unrelated. You can't get that with any of the existing operators, I think. Best you could do would be to make "unrelated" mean "false".
Last edited by Lindley; December 17th, 2008 at 08:58 AM.
-
December 17th, 2008, 09:13 AM
#10
Re: math logic confusion
Originally Posted by Lindley
Besides, for a partial ordering you need three results: true, false, and unrelated
well, in mathematical terms if R is a relation then aRb <=> (a,b) belongs to R , so what you call "unrelated" is "false" (but I understand what you mean ...).
anyway, thanks for The rule of thumb
-
December 17th, 2008, 10:17 AM
#11
Re: math logic confusion
Another method could be...
Code:
return (lhs.m_days < rhs.m_days) ? true :
((lhs.m_hours < rhs.m_hours) ? true :
((lhs.m_minutes < rhs.m_minutes) ? true :
(lhs.m_seconds < rhs.m_seconds)));
though it wouldn't score high on readability.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
December 17th, 2008, 10:22 AM
#12
Re: math logic confusion
I'll try this again.
Give the class a method, call it say GetTotalSeconds();
Code:
int MyClass::GetTotalSeconds()
{
return m_Seconds + (m_Minutes * 60) + (m_Hours * 60 * 60) + (m_Days * 60 * 60 * 24);
}
Then just compare two initialized objects.
Code:
if(object1.GetTotalSeconds() < object2.GetTotalSeconds())
-
December 17th, 2008, 10:45 AM
#13
Re: math logic confusion
Originally Posted by GCDEF
I'll try this again.
Give the class a method, call it say GetTotalSeconds();
Total Seconds can be useful for other purposes..but it the ONLY reason is for a compare. You can make this much simpler and smaller/faster
Code:
long value = m_Days << 18 | m_Hours < 12 | m_Minutes << 6 | m_Seconds;
This will calcuate a "funny number" that is monotonic (and thus can be compared)
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
December 17th, 2008, 10:48 AM
#14
Re: math logic confusion
Originally Posted by GCDEF
Give the class a method, call it say GetTotalSeconds();
Yes, and then operator< can be a non-member non-friend (though GetTotalSeconds() should be const-correct; it is not const-correct in the example).
-
December 17th, 2008, 10:53 AM
#15
Re: math logic confusion
Originally Posted by TheCPUWizard
Total Seconds can be useful for other purposes..but it the ONLY reason is for a compare. You can make this much simpler and smaller/faster
Code:
long value = m_Days << 18 | m_Hours < 12 | m_Minutes << 6 | m_Seconds;
This will calcuate a "funny number" that is monotonic (and thus can be compared)
I'll take your word for it with that one.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|