472,370 Members | 2,417 Online

# Even-Odd sorting

Hello.

It seems a year is all it takes for one's proficiency in C++ to become
too rusty. Professionally, I've been away from the language (and from
programming in general), but I still preserve an appreciation for it.

So I decided to toy with some idea, just for fun and for evaluating how
rusty I'd become. "Let me write a simple functor for sorting the
elements of a collection! I will start with a simple collection of
integers.", I thought. I then chose an unusual criterion for the
sorting: "I'd like the elements to be ordered so that the even members
should appear before the odd ones." The following is what I came up
with. The program is not producing the expected behavior and I suspect
it has to do with my predicate. It is probably not fully complying to
the requirements for such a function.

#include <iostream>
#include <set>
#include <functional>
#include <algorithm>
#include <iterator>

class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
return i % 2 == 0 && j % 2 != 0;
}
};

int main() {
std::set<int, EvenOddSortingintSet;
intSet.insert(10);
intSet.insert(7);
intSet.insert(5);
intSet.insert(18);
intSet.insert(3);
std::cout << "Even-Odd ordered set: ";
std::copy(intSet.begin(),
intSet.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}

Given the above program, the expected output should read:

Even-Odd ordered set: 10 18 3 5 7

Notice how my proposed output implies a hidden requirement of ordering
among even and odd numbers. That would be ideal, but I'd be satisfied
(at first) with an output like '18 10 5 7 3'. Would anybody care to give
me a hand?

Thank you!

--
Ney André de Mello Zunino
Jun 27 '08 #1
18 4734
Ney André de Mello Zunino wrote:
[..]
So I decided [..] "Let me write a simple functor for sorting the
elements of a collection! I will start with a simple collection of
integers.", I thought. I then chose an unusual criterion for the
sorting: "I'd like the elements to be ordered so that the even members
should appear before the odd ones." The following is what I came up
with. The program is not producing the expected behavior and I suspect
it has to do with my predicate. It is probably not fully complying to
the requirements for such a function.

#include <iostream>
#include <set>
#include <functional>
#include <algorithm>
#include <iterator>

class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
return i % 2 == 0 && j % 2 != 0;
What if they are both odd? What if they are both even? Does the
predicate satisfy the requirement of strict weak ordering?

The predicate returns 'true' if the first is even and the second is odd.
For the rest it would return 'false', right? That means that when
comparing 5 and 7 it would determine that 5 is not less than 7. And
when comparing 7 and 5 it would determine that 7 is not less than 5.
That seems to me that 5 is the same as 7. That is, 5 and 7 cannot
coexist in the set that has your 'EvenOddSorting' as the predicate.

Do the same with two evens.
}
};

int main() {
std::set<int, EvenOddSortingintSet;
intSet.insert(10);
intSet.insert(7);
After this the collection should be {10, 7}. Is it?
intSet.insert(5);
After this the collection _could_ be 10, 5, 7, or it could be 10, 7, 5,
if the predicate allowed placing both 5 and 7 next to each other. It
does not, AFAICT. So, here the collection will be {10, 7}, still.

And so on.
intSet.insert(18);
intSet.insert(3);
std::cout << "Even-Odd ordered set: ";
std::copy(intSet.begin(),
intSet.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}

Given the above program, the expected output should read:

Even-Odd ordered set: 10 18 3 5 7
OK, that's what it *should* read (you believe). What *does* it read?
>
Notice how my proposed output implies a hidden requirement of ordering
among even and odd numbers. That would be ideal, but I'd be satisfied
(at first) with an output like '18 10 5 7 3'. Would anybody care to give
me a hand?
Not sure what kind of help you are seeking. You've not specified all
the requirements for your predicate to implement it correctly. Have I
given you enough hints to go on?

V
--
Jun 27 '08 #2

On May 23, 3:41 pm, Ney André de Mello Zunino <zun...@inf.ufsc.br>
wrote:
[snip]
I then chose an unusual criterion for the
sorting: "I'd like the elements to be ordered so that the even members
should appear before the odd ones."
[snip]
The program is not producing the expected behavior and I suspect
it has to do with my predicate.
[snip]
class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
return i % 2 == 0 && j % 2 != 0;
}

};
[snip]
std::set<int, EvenOddSortingintSet;
[snip]
std::set. Note that a set can only hold unique items. That is, no two
elements a and b exist in a set such that a == b.

Your predicate tests if a < b. If a < b OR b < a then a != b. If (NOT
a < b) AND NOT (b < a) then a == b. The set uses your predicate to
determine uniqueness. Because your predicate only compares based on
parity and not values, in effect you have defined all even numbers to
be equivalent, and all odd numbers to be equivalent. Therefore your
set, which must only contain unique values, will contain one even
number, and one odd number.

If you want the value of the integers to be a criteria for uniqueness
your predicate must take that into account. You can also, then, have
sorting "within" the even and odd numbers, if you do something like

class EvenOddValueSorting {
public:
bool operator()(const int i, const int j) const {
bool i_is_even = !(i % 2);
bool j_is_even = !(j % 2);
if (i_is_even == j_is_even) // if parity is same...
return i < j; // ... compare by value only
else
return i_is_even; // ... otherwise even always < odd.
}
};

Alternatively, you can use the predicate you have now for sorting, but
do not use a container that requires value uniqueness. For example,
use a vector with your current predicate:

std::vector<intv;
v.push_back(10);
v.push_back(7);
v.push_back(5);
v.push_back(18);
v.push_back(3);
std::sort(v.begin(), v.end(), EvenOddSorting());

Doing that with EvenOddSorting will place all the even numbers before
all the odd ones. Doing it with EvenOddValueSorting will sort by
numeric value also. Note that std::sort is not stable; but you can use
std::stable_sort if that is a requirement. See:

http://www.sgi.com/tech/stl/table_of_contents.html

Jason
Jun 27 '08 #3
Victor Bazarov wrote:
What if they are both odd? What if they are both even? Does the
predicate satisfy the requirement of strict weak ordering?

The predicate returns 'true' if the first is even and the second is odd.
For the rest it would return 'false', right? That means that when
comparing 5 and 7 it would determine that 5 is not less than 7. And
when comparing 7 and 5 it would determine that 7 is not less than 5.
That seems to me that 5 is the same as 7. That is, 5 and 7 cannot
coexist in the set that has your 'EvenOddSorting' as the predicate.

Do the same with two evens.
Yes, I see what you mean and it makes perfect sense now.

[...]
OK, that's what it *should* read (you believe). What *does* it read?
Sorry for not posting the results. You were right, only 10 and 7 were
being accepted in the collection.
>Notice how my proposed output implies a hidden requirement of ordering
among even and odd numbers. That would be ideal, but I'd be satisfied
(at first) with an output like '18 10 5 7 3'. Would anybody care to
give me a hand?

Not sure what kind of help you are seeking. You've not specified all
the requirements for your predicate to implement it correctly. Have I
given you enough hints to go on?
Yes, sir, you have. Here's the modified functor class (which can
probably be further simplified):

class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
if (i % 2 == 0) {
if (j % 2 != 0) { // i is even and j is odd
return true;
} else { // both i and j are even
return i < j;
}
} else {
if (j % 2 == 0) { // i is odd and j is even
return false;
} else { // both i and j are odd
return i < j;
}
}
}
};

The program now outputs my desired results:

Even-Odd ordered set: 10 18 3 5 7

Do you see any remaining issue?

Thank you,

--
Ney André de Mello Zunino
Jun 27 '08 #4
ja************@gmail.com wrote:

[...]
class EvenOddValueSorting {
public:
bool operator()(const int i, const int j) const {
bool i_is_even = !(i % 2);
bool j_is_even = !(j % 2);
if (i_is_even == j_is_even) // if parity is same...
return i < j; // ... compare by value only
else
return i_is_even; // ... otherwise even always < odd.
}
};

Alternatively, you can use the predicate you have now for sorting, but
do not use a container that requires value uniqueness. For example,
use a vector with your current predicate:

std::vector<intv;
v.push_back(10);
v.push_back(7);
v.push_back(5);
v.push_back(18);
v.push_back(3);
std::sort(v.begin(), v.end(), EvenOddSorting());

Doing that with EvenOddSorting will place all the even numbers before
all the odd ones. Doing it with EvenOddValueSorting will sort by
numeric value also. Note that std::sort is not stable; but you can use
std::stable_sort if that is a requirement. See:

http://www.sgi.com/tech/stl/table_of_contents.html
Thank you, Jason, for your insights and suggestions. I also appreciated
how simpler your predicate looks compared to mine. Before seeing your

bool operator()(const int i, const int j) const {
if (i % 2 == 0 && j % 2 == 0 || i % 2 != 0 && j % 2 != 0) {
return i < j;
} else {
return i % 2 == 0;
}
}

But your version seems a bit easier to follow.

Regards,

--
Ney André de Mello Zunino
Jun 27 '08 #5
Ney André de Mello Zunino wrote:
Victor Bazarov wrote:
>What if they are both odd? What if they are both even? Does the
predicate satisfy the requirement of strict weak ordering?

The predicate returns 'true' if the first is even and the second is
odd. For the rest it would return 'false', right? That means that
when comparing 5 and 7 it would determine that 5 is not less than 7.
And when comparing 7 and 5 it would determine that 7 is not less than
5. That seems to me that 5 is the same as 7. That is, 5 and 7 cannot
coexist in the set that has your 'EvenOddSorting' as the predicate.

Do the same with two evens.

Yes, I see what you mean and it makes perfect sense now.

[...]
>OK, that's what it *should* read (you believe). What *does* it read?

Sorry for not posting the results. You were right, only 10 and 7 were
being accepted in the collection.
>>Notice how my proposed output implies a hidden requirement of
ordering among even and odd numbers. That would be ideal, but I'd be
satisfied (at first) with an output like '18 10 5 7 3'. Would anybody
care to give me a hand?

Not sure what kind of help you are seeking. You've not specified all
the requirements for your predicate to implement it correctly. Have I
given you enough hints to go on?

Yes, sir, you have. Here's the modified functor class (which can
probably be further simplified):

class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
if (i % 2 == 0) {
if (j % 2 != 0) { // i is even and j is odd
return true;
} else { // both i and j are even
return i < j;
}
} else {
if (j % 2 == 0) { // i is odd and j is even
return false;
} else { // both i and j are odd
return i < j;
}
}
}
};

The program now outputs my desired results:

Even-Odd ordered set: 10 18 3 5 7

Do you see any remaining issue?
Issue? Not really. I think you got it now. You can simplify the
predicate a bit by doing

if (i % 2 == j % 2)
return i < j; // for the same oddness - just compare them
else
return i % 2 == 0; // for different, 'i' is smaller if it's even

How's that?

V
--
Jun 27 '08 #6
Ney André de Mello Zunino wrote:
Hello.

It seems a year is all it takes for one's proficiency in C++ to become
too rusty. Professionally, I've been away from the language (and from
programming in general), but I still preserve an appreciation for it.

So I decided to toy with some idea, just for fun and for evaluating how
rusty I'd become. "Let me write a simple functor for sorting the
elements of a collection! I will start with a simple collection of
integers.", I thought. I then chose an unusual criterion for the
sorting: "I'd like the elements to be ordered so that the even members
should appear before the odd ones." The following is what I came up
with. The program is not producing the expected behavior and I suspect
it has to do with my predicate. It is probably not fully complying to
the requirements for such a function.

#include <iostream>
#include <set>
#include <functional>
#include <algorithm>
#include <iterator>

class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
return i % 2 == 0 && j % 2 != 0;
}
};

int main() {
std::set<int, EvenOddSortingintSet;
intSet.insert(10);
intSet.insert(7);
intSet.insert(5);
intSet.insert(18);
intSet.insert(3);
std::cout << "Even-Odd ordered set: ";
std::copy(intSet.begin(),
intSet.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}

Given the above program, the expected output should read:

Even-Odd ordered set: 10 18 3 5 7

Notice how my proposed output implies a hidden requirement of ordering
among even and odd numbers. That would be ideal, but I'd be satisfied
(at first) with an output like '18 10 5 7 3'. Would anybody care to give
me a hand?

Thank you!
Along with the other advice you got, I've re-written parts of your
original to make it what I consider cleaner.

#include <iostream>
#include <set>
#include <algorithm>
#include <iterator>

class EvenOddSorting {
private:
inline bool isEven(const int i) const {
return 0 == i % 2;
}
public:
inline bool operator()(const int i, const int j) const {
return isEven(i+j) ? i < j : isEven(i);
}
};

int main() {
std::set<int, EvenOddSortingintSet;
const int values[] = {10, 7, 5, 18, 3};
std::copy(values,
values + 5,
std::inserter(intSet, intSet.begin()));
std::cout << "Even-Odd ordered set: ";
std::copy(intSet.begin(),
intSet.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
return 0;
}

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Jun 27 '08 #7
In article <g1**********@aioe.org>, zu****@inf.ufsc.br says...

[ ... ]
class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
return i % 2 == 0 && j % 2 != 0;
}
Just FWIW, the least significant bit of a number is 1 if the number is
odd, and 0 if the number is even. As such, 'i&1' will be 1 iff i is odd.
IOW, the even/odd ordering can be written as: (i&1) < (j&1).

As has already been mentioned, for a set you also need to provide
ordering within the odd and even numbers, so you'll need to add a normal
comparison iff the LSBs are equal.

class EvenOddSorting {
// feel free to return 'i%2' if you prefer
int lsb(int i) const { return i&1; }
public:
bool operator()(int i, int j) const {
return (lsb(i) < lsb(j)) || (lsb(i) == lsb(j) && i<j);
//
// A couple of alterative possibilities that may be more understanable
// to those who don't like boolean expressions.
//
// if (lsb(i) < lsb(j))
// return true;
// return lsb(i)==lsb(j) && i<j;
//
// Possibly even more explicit alternative:
//
// if (lsb(i) < lsb(j))
// return true;
// if (lsb(j) < lsb(i))
// return false;
// return i < j;
}
};

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #8
Hello,

In article <g1**********@aioe.org>, zu****@inf.ufsc.br says...
> return i % 2 == 0 && j % 2 != 0;
Just FWIW, the least significant bit of a number is 1 if the number is
odd, and 0 if the number is even. As such, 'i&1' will be 1 iff i is odd.
IOW, the even/odd ordering can be written as: (i&1) < (j&1).
I've often been told that a good compiler would generate exactly the
same assembly code int those cases (i is an int):
i % 2 and i & 1
i * 2 and i << 1
i / 2 and i >1
and for the next powers of 2. (i * 8 and i << 3 etc.)

*Question*: has anybody really looked the assembly code generated by
your compiler in those cases? And what is your conclusion on this point?

If your compiler generates the same assembly, I do think that i % 2 is
more readable than i & 1, because the 'modulo 2' is the mathematic
operation for 'odd or even'.

If your compiler does not generate the same code, then you will have to
profile your code to choose between the two possible solutions. Anyway,
I would stick to i % 2 until there is a proof that this part of code is
an execution speed bottleneck.

Bon week-end,
--
Vincent Jacques

"S'il n'y a pas de solution, c'est qu'il n'y a pas de problÃ¨me"
Jun 27 '08 #9
Some people in this thread have suggested comparison operators that
rely on the result of (i%2) being either 0 or 1, but this may be false
in case the number is negative. Many compilers implement the division
operators so that the quotient is rounded towards zero, which imply
that i%2==-1 when i<0.

Indeed, the following comparison operators have implementation-defined
behaviour (and give a wrong result on my machine when the numbers are
{10, -7, -5, 18, 3} ):

Victor Bazarov's:
class EvenOddSorting {
public:
bool operator()(int i, int j) const {
if (i % 2 == j % 2)
return i < j; // for the same oddness - just compare them
else
return i % 2 == 0; // for different, 'i' is smaller if it's even
}
};
and an alternative suggested by Jerry Coffin:
class EvenOddSorting {
* * * * // feel free to return 'i%2' if you prefer
* * * * int lsb(int i) const { return i%2; }
public:
* * * * bool operator()(int i, int j) const {
* * * * * * * * return (lsb(i) < lsb(j)) || (lsb(i) ==lsb(j) && i<j);
};
Cheers,

Dario
Jun 27 '08 #10
Stefan Ram a écrit :
Vincent Jacques <ne*******@vincent-jacques.netwrites:
>If your compiler generates the same assembly, I do think that
i % 2 is more readable than i & 1, because the 'modulo 2' is
the mathematic operation for 'odd or even'.

I do not see how the readability of »i % 2« depends on the
code my compiler generates.
Sorry for not being clear:

I meant:
(1) there are two cases: (a) the generated code is the same or (b) it is
different.
(2) In general, I think that i % 2 is more readable than i & 1 when you
mean 'odd or even'
(3) I prefer to write readable code over micro-optimized code.

Then I go on the two cases of (1):
case (a): from (2), I write i % 2
case (b): from (3) and (2), I write i % 2 until I'm told (by my
customer, by my hierarchy, etc.) that I *have* to write micro-optimized
code.
»%« is /not/ the mathematical operation »modulo«.
[snip the exact meaning of %]
You're right. Yet, the reminder of the division of i by 2 carries more
about 'odd or even' than the bitwise and between i and 1. (motivation
for (2))
>If your compiler does not generate the same code, then you will have to
profile your code to choose between the two possible solutions.

I do not have to profile, because I usually do not write C++
source code for a specific compiler and execution environment,
I usually do not invest time in such non-portable
microoptimizations.
So do I, usually. But, from (2), I assume that the comment from Jerry
Coffin is motivated by an hypothetical win of performance. That's why I

Cheers,
--
Vincent Jacques

"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème"
Jun 27 '08 #11
In article <48*********************@news.orange.fr>, newsgroup@vincent-
jacques.net says...

[ ... ]
I've often been told that a good compiler would generate exactly the
same assembly code int those cases (i is an int):
i % 2 and i & 1
i * 2 and i << 1
i / 2 and i >1
and for the next powers of 2. (i * 8 and i << 3 etc.)

*Question*: has anybody really looked the assembly code generated by
your compiler in those cases? And what is your conclusion on this point?
Yes. Given test code like this:

int lsb1(int i) { return i&1; }
int lsb2(int i) { return i%2; }

Microsoft (VC++ 7.1) produces code like this (after cleaning up a lot of
cruft):

lsb1:
mov eax, DWORD PTR _i\$[esp-4]
and eax, 1
ret 0

lsb2:
mov eax, DWORD PTR _i\$[esp-4]
and eax, -2147483647 ; 80000001H
jns SHORT \$L286
dec eax
or eax, -2 ; fffffffeH
inc eax
\$L286:
ret 0

Using g++ (4.3.0) the result is marginally different (again, after
cleaning things up a bit):

lsb1:
movl 8(%ebp), %eax
popl %ebp
andl \$1, %eax
ret

lsb2:
movl 8(%ebp), %eax
popl %ebp
movl %eax, %edx
shrl \$31, %edx
andl \$1, %eax
subl %edx, %eax
ret

Even if you don't read assembly language, it's pretty easy to see that
the version using '%' is substantially longer in both cases. More
importantly than the difference in length is the difference in effect --
the first is simple and always works. The extra complexity in the second
not only slows it down, but _stops it from working correctly_!

[ ... ]
If your compiler does not generate the same code, then you will have to
profile your code to choose between the two possible solutions. Anyway,
I would stick to i % 2 until there is a proof that this part of code is
an execution speed bottleneck.
Dario's point was NOT related to speed -- it was related to correct
operation. The code was based on an assumption that 'i%2' would always
yield 0 or 1. That's NOT the case -- when i is negative, it's allowed to
yield -1.

Now, it's certainly true that C and C++ make allowances for some
ancient, oddball hardware. It's fairly safe for a lot of people to
assume their code will never deal with such things, so they can safely
make some assumptions even though they aren't guaranteed to always be
true. Assuming that 'i%2' will always yield 0 or 1 isn't really one of
those safe assumptions though -- yielding -1 isn't some strange
possibility that will only ever happen with a strange compiler on a
weird machine almost nobody's ever seen or heard of. Quite the contrary,
it's a common occurrence with average, everyday compilers running on
extremely common hardware (the Intel/AMD x86/x64).

At least with the tested compilers, the code using 'i&1' will almost
certainly be faster -- but the fact that it works correctly is FAR more
important.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #12
In article <od****************@ram.dialup.fu-berlin.de>, ra*@zedat.fu-
berlin.de says...

[ ... ]
A function to tell whether a number is odd, might be written
as follows.

inline odd( int const i ){ return( i >= 0 ? i : -i )% 2; }

or

inline odd( int const i ){ return( i >= 0 ? i : -i )& 1; }

As you wrote, whether one of them is faster can only be
determined relative to a specific environment by a
measurement.
Yes, but it might also be written as:

inline odd(int i) { return i & 1; }

IMO, this is simpler and more readable than either of the previous
possibilities -- and given the requirements of both C and C++, it's just
as dependable and portable as the alternatives.

As an aside, I'd note that all of these need a return type added --
either bool or int would work, though given the name you've chosen, bool
would be the obvious choice.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #13
In article <od****************@ram.dialup.fu-berlin.de>, ra*@zedat.fu-
berlin.de says...
Jerry Coffin <jc*****@taeus.comwrites:
inline odd(int i) { return i & 1; }
IMO, this is simpler and more readable than either of the previous

C++ permits 2's complement, 1's complement, signed magnitude
and possibly other representations for integral types. It is
not obvious to me, that the above definition is correct for
all these representations when i is negative. (It also is not
obvious to me that it is not correct for all these representations.)
It's always true in those three representations. In theory C++ (but not
C, anymore) allows other "pure binary" representations, but 1) only
those three actually exist, and 2) being a pure binary representation
means that it would continue to work anyway, even on some representation
that doesn't exist.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #14
ra*@zedat.fu-berlin.de:
>inline odd( int const i ){ return( i >= 0 ? i : -i )% 2; }
inline odd( int const i ){ return( i >= 0 ? i : -i )& 1; }
Jerry Coffin:
inline odd(int i) { return i & 1; }
Myself:
inline bool odd( int i ) { return i % 2; }
As an aside, I'd note that all of these need a return type added --
either bool or int would work, though given the name you've chosen, bool
would be the obvious choice.
If they return a bool, all the four versions are correct and allow us to
compare oddity
if( odd( i ) == odd( j ) ) { ... }
because we do not rely on i%2 returning only 0 or 1.

As it was pointed out in this thread, it is not true if they return int.
--
Vincent Jacques

"S'il n'y a pas de solution, c'est qu'il n'y a pas de problÃ¨me"
Jun 27 '08 #15
In article <MP***********************@news.sunsite.dk>,
jc*****@taeus.com says...

[ one's complement, two's complement, sign/magnitude and 'i&1' ]
It's always true in those three representations.
Thinking about it a moment longer, that's not true. It works on
sign/magnitude and two's complement, but breaks on one's complement.

So, the original suggestion breaks on two's complement, and my version
breaks on one's complement. At least for me, one's complement machines
fall into that category that I feel fairly safe ignoring -- and I'm one
of probably fewer than a half dozen regular participants here who's
actually worked on a machine that used one's complement for integers.

In theory, I can also see the remote possibility of a biased
representation, in which the bias was odd, where it would also break. I
can't quite imagine anybody doing that though: given the requirement
that non-negative signed numbers and unsigned numbers have the same
representation, you'd need to use the same bias on unsigned numbers as
well, and making math on those work correctly seems a bit cumbersome
(about the only obvious way I can think of would be to remove the bias,
do the math, then reapply the bias). Of course, such a representation
isn't allowed under either C99 or C++ 0x (except under the as-if rule,
if the implementation made it always act like an allowed representation,
of course).

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #16
On May 24, 4:14 am, Dario Saccavino <kath...@gmail.comwrote:
Some people in this thread have suggested comparison operators that
rely on the result of (i%2) being either 0 or 1, but this may be false
in case the number is negative.
Victor Bazarov's:
and an alternative suggested by Jerry Coffin:
What am I, chopped liver? :_(

<g>

Jason
Jun 27 '08 #17
On May 25, 4:02 am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.comwrote:
On May 24, 4:14 am, Dario Saccavino <kath...@gmail.comwrote:
Some people in this thread have suggested comparison operators that
rely on the result of (i%2) being either 0 or 1, but this may be false
in case the number is negative.
Victor Bazarov's:
and an alternative suggested by Jerry Coffin:

What am I, chopped liver? :_(

<g>

Jason
try this
class EvenOddSorting {
public:
bool operator()(const int i, const int j) const {
return (i % 2 == 0 && j % 2 != 0) || ((i + j) % 2 == 0 && (i
< j));
}

};

btw:
the original code have some problem when gcc compile it. output is 10,
7, the size of intSet is 2.
I guess that the gcc's set implementation compare number i and j by
if(!( compare(i,j) && compare(j,i) ) return; so 10 == 18, and 3 == 5
== 7 under the comparator.
Jun 27 '08 #18
Jerry Coffin wrote:
In article <od****************@ram.dialup.fu-berlin.de>, ra*@zedat.fu-
berlin.de says...

[ ... ]
> A function to tell whether a number is odd, might be written
as follows.

inline odd( int const i ){ return( i >= 0 ? i : -i )% 2; }

or

inline odd( int const i ){ return( i >= 0 ? i : -i )& 1; }

As you wrote, whether one of them is faster can only be
determined relative to a specific environment by a
measurement.

Yes, but it might also be written as:

inline odd(int i) { return i & 1; }

IMO, this is simpler and more readable than either of the previous
possibilities -- and given the requirements of both C and C++, it's just
as dependable and portable as the alternatives.

As an aside, I'd note that all of these need a return type added --
either bool or int would work, though given the name you've chosen, bool
would be the obvious choice.
It might also be more correctly written as
template<typename T>
inline bool even(const T t) { return (t % 2) == 0; }

template<typename T>
inline bool odd(const T t) { return !even(t); }

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Jun 27 '08 #19

This thread has been closed and replies have been disabled. Please start a new discussion.