Definition
Even popcount
Even number of 1-bits → evil; odd → odious.
An evil number has an even count of 1 bits in binary; an odd count means odious. This tutorial covers Hamming weight, popcount helpers, manual loops, a live preview, worked JavaScript examples, edge cases, and complexity.
Even popcount
Even number of 1-bits → evil; odd → odious.
1111
Four ones (even) so 15 is evil.
Built-in
Fastest readable JavaScript one-liner for popcount.
0 ones
Zero has popcount 0, and 0 is even.
Try any n
See popcount and evil/odious instantly.
Single check
Kernighan can reduce work to O(popcount).
Evil numbers are nonnegative integers whose binary form has an even number of 1 bits. If the count is odd, the number is called odious. Example: 15 is 1111 (four ones) → evil; 7 is 111 (three ones) → odious.
The count of 1-bits is the Hamming weight (popcount). Evil means even Hamming weight; odious means odd.
It turns even/odd thinking into bit-level parity — a bridge from simple modulo checks to popcount and bit tricks.
Only the parity of the 1-bit count matters.
0 is evil (zero ones is even).
Odd popcount means odious, not evil.
This page scopes the definition to n ≥ 0.
In short: count the 1-bits; if that count is even, n is evil.
Given a nonnegative integer n, decide whether its binary popcount is even.
// 15 → 1111 → 4 ones → evil
// 7 → 111 → 3 ones → odious
// 0 → 0 → 0 ones → evil | Item | Type | Description |
|---|---|---|
n | number | Nonnegative integer (this page rejects negatives). |
| Return / print | boolean / text | true if n is evil (even popcount). |
function isEvil(n) {
return popCount(n) % 2 === 0;
} | Method | Idea | Notes |
|---|---|---|
popCount(n) | Unsigned >>> loop, then % 2 | Best default helper in JavaScript |
| Divide by 2 | % 2 / Math.floor(n / 2) to read bits | Great for teaching binary |
| Kernighan | n &= n - 1 clears one set bit | O(popcount) steps |
| Goal | Pattern |
|---|---|
| Popcount | popCount(n) |
| Evil test | popCount(n) % 2 === 0 |
| Binary string | bin(n) or format(n, "b") |
| Clear lowest set bit | n &= n - 1 |
| Classic evil | 0, 3, 5, 6, 9, 10, 15 |
| Classic odious | 1, 2, 4, 7, 8 |
Related parity ideas — different levels of abstraction.
popcount evenEven count of 1-bits
popcount oddOdd count of 1-bits
n % 2 === 0Value parity, not bit count
say nonnegativeScope the definition before coding
Reach for evil/odious checks when popcount parity matters.
Tests binary understanding without heavy algorithms.
Natural next step: parity of bits instead of the value.
Print all evil numbers in 1…N for small N.
Makes Hamming weight concrete with 15 vs 7.
State nonnegative scope before coding.
Key benefit: one short boolean check that teaches popcount parity and pairs cleanly with even/odd value parity.
Nonnegative integers only for this definition (within JavaScript safe range).
Three complete JavaScript programs — unsigned popcount, range scan with division, and Kernighan popcount. Click View Output to reveal sample console results.
Unsigned popcount helper with a parity check.
Count set bits with >>>, then test parity.
function popCount(n) {
let count = 0;
let x = n >>> 0;
while (x !== 0) {
count += x & 1;
x >>>= 1;
}
return count;
}
function isEvil(n) {
if (n < 0) {
return false;
}
return popCount(n) % 2 === 0;
}
const number = 15;
if (isEvil(number)) {
console.log(`${number} is an Evil Number.`);
} else {
console.log(`${number} is not an Evil Number.`);
} popCount(15) is 4, and 4 is even — so 15 is evil. Negatives return false under this page’s nonnegative policy.
Manual bit reading by dividing by 2.
Range output matches the classic sample.
function isEvilNonNeg(num) {
let ones = 0;
while (num > 0) {
if (num % 2 === 1) {
ones += 1;
}
num = Math.floor(num / 2);
}
return ones % 2 === 0;
}
console.log("Evil numbers in the range 1 to 10:");
let line = "";
for (let i = 1; i <= 10; i++) {
if (isEvilNonNeg(i)) {
line += i + " ";
}
}
console.log(line.trim()); The loop counts ones in binary by repeatedly taking % 2 and dividing by 2. Inclusive end uses for (i = 1; i <= 10; i++).
Clear one set bit per step for O(popcount) work.
n &= n - 1 removes the lowest set bit each iteration.
function popcountKernighan(n) {
let ones = 0;
while (n) {
n &= n - 1;
ones += 1;
}
return ones;
}
function isEvilKernighan(n) {
if (n < 0) {
return false;
}
return popcountKernighan(n) % 2 === 0;
}
for (const n of [15, 7, 0, 3]) {
const label = isEvilKernighan(n) ? "evil" : "odious";
console.log(`${n}: ${label} (ones=${popcountKernighan(n)})`);
} Each n &= n - 1 clears exactly one set bit, so the loop runs once per 1-bit. Prefer a clear popcount helper in production; mention Kernighan as an interview follow-up.
Use popCount(n), a divide-by-2 loop, or Kernighan.
Even ones → evil; odd ones → odious.
Apply the same helper for each value in 1…N.
Even popcount → evil; otherwise odious.
n = 15Trace popcount for the classic evil example.
| Step | Binary / action | Ones so far |
|---|---|---|
| 1 | 15 = 1111 | — |
| 2 | popCount(n) / four 1s | 4 |
| 3 | 4 % 2 == 0 | Evil |
For contrast, 7 = 111 has 3 ones → odious.
Where evil/odious checks show up beyond the interview prompt.
Popcount parity without heavy bit algorithms.
Example: write isEvil(n).
Connect decimal values to 1-bit counts.
Example: chalkboard 15 vs 7.
Contrast value parity with bit-count parity.
Example: 6 is even and evil.
List evil numbers in a classroom interval.
Example: 1 to 10 → 3 5 6 9 10.
Kernighan loop and hardware popcount.
Example: n &= n - 1.
Confirm 0 is evil before harder bit problems.
Example: ask “is zero evil?” first.
Pro Tip: say “evil = even popcount; odious = odd” before coding — it prevents mixing with decimal even/odd.
Why this pattern works well in interviews and classwork.
One sentence: even count of 1-bits.
popCount(n), divide-by-2, and Kernighan all work.
15 vs 7 makes verification quick.
Odious, zero, and Kernighan are natural next questions.
Pro Tip: lead with a clear popCount helper; offer a manual loop if asked to avoid helpers.
Small habits that keep evil-number solutions interview-ready.
Say n ≥ 0 before coding.
State that 0 is evil (zero ones).
Evil and odious classics catch parity mistakes.
Use the builtin unless asked for a manual loop.
Mention the odd-popcount complement in interviews.
Pro Tip: do not confuse “evil” with “even value” — 7 is odd but odious; 6 is even and evil.
Mistakes that commonly break evil-number solutions.
Checking n % 2 === 0 instead of popcount parity.
→ Count 1-bits, then check that count’s parity.
Thinking zero has no classification.
→ Zero ones is even → evil.
Applying popcount to negatives without a policy.
→ Reject or define two’s-complement rules explicitly.
Padding to a fixed width and counting zeros as ones.
→ Only count 1-bits in the canonical nonnegative form.
Using for (i = 1; i < 10; i++) when 10 should be included.
→ Use for (i = 1; i <= 10; i++) for inclusive 1…10.
Most definitions use nonnegative integers. Keep that policy clear in your code.
n = 0Evil because ones count is 0 (even).
This page rejects negatives for clarity.
Use canonical nonnegative binary representation.
Use inclusive loops when required by the question.
7, 1, 2, 4, 8 are common odious examples.
For values beyond safe integers, use BigInt or a division loop.
Handy follow-ups interviewers sometimes ask.
Try these variations to lock in the pattern.
popCount(n) or manual bit loops.Quick Takeaway: count the 1-bits; if that count is even, the number is evil.
| Operation | Time | Extra space |
|---|---|---|
| Single number popcount | O(bits) | O(1) |
| Kernighan method | O(popcount) | O(1) |
| Range scan | O(range · bits) | O(1) |
An evil number has an even count of 1-bits in binary; an odd count means odious. Use a popCount helper, keep a nonnegative policy, and remember that zero is evil.
Practice the three examples above, then continue to factorial for a classic loop-and-product warm-up.
Do not confuse popcount parity with decimal even/odd — and mention odious as the complement.
popCount helpern % 2 as the evil testCheck popcount parity the interview-friendly way.
Even 1-bits
Definition0 is evil
TriviapopCount(n)
CodeOdious = odd
PairO(bits)
AnalysisThe opposite of an evil number is an odious number. Evil means an even count of 1 bits; odious means odd.
Learn iterative and recursive ways to compute n! in JavaScript.
9 people found this page helpful