Check Evil Number in C#

Beginner
⏱️ 9 min read
📚 Updated: May 2026
🎯 2 Code Examples
Popcount parity

What you’ll learn

  • What evil means: an even count of 1 bits in binary — and the opposite word odious when that count is odd.
  • Two C# styles: peel bits with uint and shifts, or build a binary string with Convert.ToString(n, 2) and count '1' characters.
  • A range demo (110) plus a live preview that prints binary, popcount, and why the verdict follows.

Overview

Computers store integers as bits. An evil number is just a nonnegative integer whose binary spelling uses an even number of 1s. Count those ones (sometimes called population count or Hamming weight), then check whether that count is divisible by 2.

Two programs

One checks 15 with bitwise counting; the other lists evil values from 1 to 10.

Live preview

Shows binary, how many ones, even-or-odd reasoning, and the evil vs odious verdict.

Interview polish

Mentions 0, nonnegative definitions, and optional BitOperations.PopCount on modern .NET.

Prerequisites

Comfortable with small C# programs, loops, and reading tiny binary examples like 1011.

  • C# basics: using System;, class Program, Main, string interpolation.
  • Operators &, >>, and remainder % for parity.
  • Optional: casting nonnegative int to uint for bitwise walks.

What is an evil number?

A nonnegative integer n is evil when its binary representation contains an even number of 1 digits. If that count is odd, mathematicians say n is odious.

This is not about “good” or “bad” numbers — only about counting ones in base 2. Do not mix it up with “even” in decimal.

Evil popcount(n) % 2 == 0
Odious popcount(n) % 2 == 1
Zero evil (0 ones)

Hamming weight (population count)

Expand n in base 2 as n = ∑ bi 2i where each bi is 0 or 1. The sum of those bits s2(n) = ∑ bi is the Hamming weight. Then n is evil exactly when s2(n) is even.

15

15 = 8 + 4 + 2 + 1, binary 1111, so s2(15) = 4 — four is even, hence evil.

Quick examples

15 Evil
Binary
1111 — four ones
7 Odious
Binary
111 — three ones

Pattern: flipping one bit toggles odd/even population count, so neighbours on the number line do not always share the same label.

Live preview

Nonnegative integers inside JavaScript’s safe range. You get binary, a plain count of ones, and why “evil” follows from even parity.

Try 0, 7, or 10. Negatives are rejected here so the widget matches the usual nonnegative definition.

Live result
Press “Classify” to see binary, popcount, and why the number is evil or odious.

Algorithm

Goal: given nonnegative n, decide whether the number of 1-bits in binary is even.

Population count

Either peel the lowest bit with n & 1 and shift (uint recommended), or halve with n % 2 and n / 2, or scan a binary string.

Parity check

Evil means count % 2 == 0. Enumerating a range repeats the same test per index.

📜 Pseudocode

Pseudocode
function popcount(n):  // n >= 0
    c ← 0
    while n > 0:
        c ← c + (n mod 2)
        n ← floor(n / 2)
    return c

function isEvil(n):
    return (popcount(n) mod 2) = 0
1

Single value with bitwise counting

CountSetBits walks bits on a uint cast so shifts behave predictably. IsEvilNumber rejects negatives because the textbook definition uses nonnegative integers only.

c#
using System;

class Program
{
    static int CountSetBits(uint n)
    {
        int count = 0;

        while (n != 0)
        {
            count += (int)(n & 1);
            n >>= 1;
        }

        return count;
    }

    static bool IsEvilNumber(int number)
    {
        if (number < 0)
            return false;

        int setBitsCount = CountSetBits((uint)number);
        return setBitsCount % 2 == 0;
    }

    static void Main()
    {
        int number = 15;

        if (IsEvilNumber(number))
            Console.WriteLine($"{number} is an evil number.");
        else
            Console.WriteLine($"{number} is not an evil number.");
    }
}

Explanation

Each loop trip looks only at the rightmost bit, adds 0 or 1, then shifts everything right.

count += (int)(n & 1);

Mask. n & 1 is 1 when the lowest bit is set.

n >>= 1;

Shift. Drops the bit you just counted so the next iteration sees the neighbor.

return setBitsCount % 2 == 0;

Evil rule. Even popcount → evil; odd → odious.

2

Evil numbers from 1 to 10 (binary string)

Uses Convert.ToString(num, 2) so beginners can see 1 digits in a string before counting them — same evil list as the classic homework output.

c#
using System;

class Program
{
    static bool IsEvil(int num)
    {
        string binaryRepresentation = Convert.ToString(num, 2);

        int countOnes = 0;
        foreach (char digit in binaryRepresentation)
        {
            if (digit == '1')
                countOnes++;
        }

        return countOnes % 2 == 0;
    }

    static void Main()
    {
        Console.WriteLine("Evil numbers in the range 1 to 10:");

        for (int i = 1; i <= 10; i++)
        {
            if (IsEvil(i))
                Console.Write(i + " ");
        }

        Console.WriteLine();
    }
}

Explanation

Base 2 conversion produces a text like "101"; counting '1' characters reproduces popcount for nonnegative inputs.

foreach (char digit in binaryRepresentation)

Readable scan. Easy to debug because you can print the string beside the tally.

Optimization and APIs

BitOperations.PopCount (.NET 5+, System.Numerics): hardware-accelerated popcount when available — still remember the parity definition for interviews.

Kernighan trick. Repeatedly clearing the lowest set bit (n &= n - 1 on unsigned) counts iterations equal to popcount — handy when only the parity matters via XOR folding.

Interview: verbalize nonnegative definition, mention uint shifts, contrast evil vs decimal even.

❓ FAQ

Take a nonnegative integer, write it in base 2 (binary), and count how many digits are 1. If that count is even — including zero — the number is called evil.
If the count of 1-bits is odd, the number is odious instead. Every nonnegative integer is either evil or odious.
Yes. Zero is 0 in binary, so there are zero ones, and zero is an even count.
15 is 1111 in binary — four ones. Four is even, so 15 is evil.
No — decimal even/odd is different. Evil uses parity of the count of 1-bits in binary. For example, 3 is evil but odd in decimal.
For nonnegative values, casting to uint keeps right shifts clean while you peel bits: there is no sign bit confusing the walk. The outer method still takes int if your homework uses int literals.
One number needs time proportional to how many binary digits it has — O(log n) in the value n. Scanning every index from a to b adds roughly O((b - a + 1) log U) where U is the largest value.

🔄 Input / output examples

Swap the literal in Example 1 or widen the loop in Example 2. Reading from the console looks like int n = int.Parse(Console.ReadLine()); after validating input.

nBinaryPopcountEvil?
000Yes
3112Yes
71113No (odious)
1511114Yes

Edge cases and pitfalls

Most slips come from mixing definitions or forgetting how negatives look in binary strings.

Zero

n = 0

Popcount 0 is even — zero counts as evil under the usual convention.

Negatives

Convert.ToString on negatives

For signed integers, two’s complement strings look huge and confusing for beginners — stick to n ≥ 0 or decide the rule up front.

Words

Odious vs evil

Interviewers may ask you to print both labels or explain parity toggling under n XOR 1-style intuition.

Performance

Huge loops

Building strings per value in a giant range costs allocations — bitwise popcount is leaner at scale.

⏱️ Time and space complexity

OperationTime (one n)Extra space
Bitwise popcountO(log n) bitsO(1)
String conversion + scanO(log n)O(log n) for the string
Range [1, U]O(U log U) naive chaindepends on method

BitOperations.PopCount still reflects bit-width work but hides the inner loop inside the runtime.

Summary

  • Definition: evil = even popcount in binary; otherwise odious.
  • Code paths: bitwise uint loop vs binary string — both pair with % 2 on the count.
  • Watch-outs: nonnegative convention; string tricks on negatives; optional hardware popcount.
Did you know?

The complementary class is odious numbers: nonnegative integers whose binary form has an odd number of 1 bits. The words “evil” and “odious” are playful math labels — they describe bit patterns, not character.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful