Is it possible to say if there is a even or a odd number of "1" bit in a binary representation of an int in C with a single test ? If no what is the fastest way to do it ?
-
Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/162247/discussion-on-question-by-user9157389-how-to-find-if-there-is-a-even-or-a-odd-nu). – Bhargav Rao Dec 31 '17 at 12:28
-
If you enter a new question asking something like “What is an efficient way to iterate with known parity” and explaining the problem in more detail, you may attract more relevant answers. Here is one possibility: `for (unsigned i = 0; i < Limit; i += 2) { unsigned i0 = i ^ i>>1; unsigned i1 = i0 ^ 1; DoEvenParityStuff(i0); DoOddParityStuff(i1); }`. That requires that Limit be a power of two. If it is not, modifications can be made. – Eric Postpischil Jan 01 '18 at 00:13
5 Answers
One way to go about this is to count the number of bits and check the least-significant bit to see if the value is odd or even if it's 1
or 0
respectively. Given a 32-bit integer, we can count the number of 1
s in its binary representation, Hamming Weight, through some clever bit manipulation. There's a good answer on find the Hamming Weight already here, and it also speaks on efficiency.
Take this algorithm of find the Hamming weight through sideway-accumulating addition. hasOddCount
returns 1
if x
has an odd number of 1
s.
int hasOddCount(int x) {
int first = 0x11 | (0x11 << 8);
int second = first | (first << 16);
int mask = 0xf | (0xf << 8);
int count = 0;
int sum = second & x;
sum = (x>>1 & second) + sum;
sum = (x>>2 & second) + sum;
sum = (x>>3 & second) + sum;
sum = sum + (sum >> 16);
sum = ((sum & mask) + (mask & (sum >> 4)));
count = (((sum >> 8) + sum) & 0x3f);
//count is the Hamming weight, & by 0x1 to see if it's odd
return count & 0x1;
}

- 1,895
- 3
- 15
- 29
-
This can be simplified, parity can be computed without computing the whole hamming weight – harold Dec 31 '17 at 02:05
Maybe not the fastest, but it works and is pretty simple:
int evenNumberOfOnes(unsigned int num)
{
int n=0;
while(num > 0) {
n ^= num;
num = num >> 1;
}
return n & 1;
}
Thanks to @EricPostpischil for tips about improvement.

- 30,332
- 17
- 55
- 95
-
(a) Counting bits is easy. The question asks for speed, which requires some effort. (b) Recursion is a bad way to do this. (c) Instead of `1 + nOnes(num >> 1)`, you could use `1 ^ nOnes(num >> 1)` so the final result is just one bit. (d) `num >> 1` is not defined by the C standard if `num` is negative. – Eric Postpischil Dec 31 '17 at 02:11
-
Since OP is not presenting any solution on his own, I don't feel I can assume anything, but you're right about the recursion. I'll remove that version. – klutt Dec 31 '17 at 02:14
-
You can change `if (num % 2) n++;` to `n ^= num;` and `return n;` to `return n & 1;`. – Eric Postpischil Dec 31 '17 at 02:17
-
-
With that change, “It gives you the number of ones” is no longer true. The idea of the XOR is that it is just for computing parity (the evenness or oddness of the number of set bits), not for counting bits. `n ^= num` is likely faster than the previous code (unless the compiler optimizes the previous code pretty well, but it only tracks parity, not a count. – Eric Postpischil Dec 31 '17 at 02:23
-
@EricPostpischil You're right. I was not thinking and just pasted what you wrote. – klutt Dec 31 '17 at 02:26
-
Since you have now noticed that you can just XOR all the bits, you could take the next step too and shuffle the XORs into a more balanced tree which can be evaluated level-by-level with bit-level parallelism. – harold Dec 31 '17 at 02:33
-
-
If only the high bit is set, it takes 32 shifts to find it. This code https://stackoverflow.com/a/37558380/597607 just takes one round. – Bo Persson Dec 31 '17 at 15:34
I'm sure this is not the least possible code, but it's short and understandable;
#include <stdio.h>
int main(int argc, const char * argv[]) {
unsigned x;
int count;
scanf("%u\n",&x);
for(count=0;x;x>>=1)
if(x&1)
++count;
puts(count&1?"odd":"even");
return(0);
}
BTW: I'm writing code with a .05 blood alcohol level, I didn't check this, and I might be embarrassed tomorrow if I got this simple task wrong. Please do not put this code into anything that operates thermonuclear weapons or driverless cars.
EDIT: After seeing other's answers which may also be correct &| tricky; The fastest code would really depend on architecture. Modulus is only super fast on some CPUs, on others it will eat a lot of cycles. Everything does shift in about the same few cycles.

- 123,740
- 17
- 206
- 299

- 112
- 7
-
@Matteo While your edits are semantically correct, they were unneeded and overly pedantic. I had good reason for the specificity of my s uint_fast32_t. It was a subtle way to tell the obviously neophyte programmer to pay attention to architecture as well as sign vs unsigned. – EddingtonsMonkey Dec 31 '17 at 02:52
-
They were needed, period. `%ud\n` means "an `unsigned` followed by a literal `d` and arbitrary whitespace"; you don't want that `d` and if you want to use `uint_fast32_t` you have to use the corresponding macro for `scanf` - `SCNuFAST32`, as `"%u"` is for `unsigned int` only, and the very point of `uint_fast32_t` is that it may be some other type. So, as it was it was both confusing (`d`) and wrong (not just semantically - on e.g. an Arduino that `scanf` would result in UB). – Matteo Italia Dec 31 '17 at 09:36
-
The `uint_fast32_t` was completely inessential to the answer (who asked for 32 bits?), so instead of looking up `SCNuFAST32` (which I did now, and took a good three minutes) and confusing further the answer with the additional complexity (if you want to eat the trailing whitespace now you have to write something like `scanf(SCNuFAST32 "\n", &x);`, so now you have to explain what that macro is, why it's needed in first place and token pasting as well) I just used `unsigned`, which has a nice and universally known `scanf` specifier and is pretty much the fastest type you can use. – Matteo Italia Dec 31 '17 at 09:36
-
TL;DR: the `scanf` *was* wrong; I stayed on the lazy side of the spectrum while fixing it because the additional complexity of a correct fix that included `uint_fast32_t` IMO wasn't really worth it, and the priority was to have a working and correct answer in place exemplifying the trivial algorithm. Feel free to reintroduce `uint_fast32_t`, but if you do so make sure you use the correct `scanf` specifier. – Matteo Italia Dec 31 '17 at 09:42
-
My apologies. I am humbled. I used uint_fast32_t to avoid having to check the size of the int. – EddingtonsMonkey Dec 31 '17 at 12:31
int parity(int n) {
int p = 0;
for (;n;n>>=1) {
p = (n&1) ? 1-p : p;
}
return p;
}
will return zero iff the number of 1's in argument n is even. Simple test:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
int main() {
srand(time(NULL));
for (int i=0;i<100;i++) {
int n = rand();
printf("%d has an %s number of 1's \n", n, parity(n) ? "odd" : "even");
}
}

- 769
- 9
- 19
I post this as a new answer since it's a bit hackish and a bit different from my other answer.
int evenNumberOfOnesFast(unsigned int num)
{
unsigned char *b;
b = (unsigned char *)#
unsigned char par[4]={0};
for(int i=0; i<8; i++) {
for( int j=0; j<4; j++) {
par[j]^=b[j];
b[j]=b[j] >> 1;
}
}
return (par[0] ^ par[1] ^ par[2] ^ par[3]) & 1;
}
Here, I assume that an int
is 4 bytes. I hoped that this would enable the cpu to do some stuff in parallel in the pipeline. I'm not sure if that's the case, but this was about twice as fast as my previous version.
Here is the main function to test it:
#define N 10000000
int main()
{
int * arr = malloc(N*sizeof(*arr));
int * par = malloc(N*sizeof(*par));
// Random values to prevent optimizer from just removing the code
srand(time(NULL));
for(int i=0; i<N; i++)
arr[i]=rand();
// Correctness check
for(int i=0; i<N; i++)
if(evenNumberOfOnes(arr[i]) != evenNumberOfOnesFast(arr[i])) {
perror ("Error");
exit(EXIT_FAILURE);
}
clock_t begin, end;
double time_spent;
begin = clock();
for(int i=0; i<N; i++)
par[i]=evenNumberOfOnes(arr[i]);
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf(" Time: %f\n", time_spent);
begin = clock();
for(int i=0; i<N; i++)
par[i]=evenNumberOfOnesFast(arr[i]);
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf(" Time: %f\n", time_spent);
}
And the result:
$ cc r.c -O3 -Wall -Wextra
$ ./a.out
Time: 0.201635
Time: 0.093152
However, I also tested the solution hasOddCount
that @Miket25 provided, and it is actually about ten times faster than my fast variant.

- 30,332
- 17
- 55
- 95
-
You need a new compiler. Mine (Apple LLVM 9.0.0) optimizes away nearly the entire program since no results are produced from the `par` array. (Writing to it has no “observable” effects.) You can declare `par` as `volatile int *par` to defeat compiler optimization. – Eric Postpischil Dec 31 '17 at 03:59
-