How to Check If a Number Is a Spy Number in Java
Introduction
A spy number is another refreshingly simple addition to our collection of special-number checks. It asks a single, straightforward question:
Does the sum of a number's digits equal the product of its digits?
This makes it an excellent companion problem to the Harshad number check. Both problems involve computing values from a number's digits and comparing the results, although they use different operations:
- Harshad Number: Compare the original number with the sum of its digits using divisibility.
- Spy Number: Compare the sum of the digits with the product of the digits.
In this guide, you'll learn:
- What a spy number is
- How to check it using a while loop
- How to solve it using recursion
- How to print all spy numbers within a range
- Why numbers containing a zero digit behave differently
- Best practices, common mistakes, interview tips, and FAQs
What Is a Spy Number?
A spy number is a number whose sum of digits is equal to the product of its digits.
The simplest non-trivial example is 1124.
Digit sum:
1 + 1 + 2 + 4 = 8
Digit product:
1 × 1 × 2 × 4 = 8
Since both values are equal, 1124 is a spy number.
Another interesting fact is that every single-digit number (0–9) is also considered a spy number because the sum and product of a single digit are simply that digit itself.
For example:
| Number | Digit Sum | Digit Product | Spy Number? |
|---|---|---|---|
| 3 | 3 | 3 | ✅ Yes |
| 7 | 7 | 7 | ✅ Yes |
| 9 | 9 | 9 | ✅ Yes |
Method 1: Using a While Loop
This is the standard and most commonly used approach.
The algorithm calculates both the sum and the product of the digits during a single traversal of the number.
public class SpyNumberCheck {
public static void main(String[] args) {
int num = 1124;
int sum = 0;
int product = 1;
while (num != 0) {
int digit = num % 10;
sum += digit;
product *= digit;
num /= 10;
}
if (sum == product) {
System.out.println("The number is a spy number.");
} else {
System.out.println("The number is not a spy number.");
}
}
}
How This Works
The program processes one digit at a time.
For each digit:
- Add it to the running sum.
- Multiply it with the running product.
- Remove the last digit from the number.
Both calculations happen in the same loop, making the solution efficient.
Step-by-Step Trace
For num = 1124:
| Iteration | Number (Before) | Digit | Running Sum | Running Product | Number (After) |
|---|---|---|---|---|---|
| 1 | 1124 | 4 | 4 | 4 | 112 |
| 2 | 112 | 2 | 6 | 8 | 11 |
| 3 | 11 | 1 | 7 | 8 | 1 |
| 4 | 1 | 1 | 8 | 8 | 0 |
After processing every digit:
Sum = 8
Product = 8
Since both values are equal:
8 == 8
the program concludes that 1124 is a spy number.
Output
The number is a spy number.
Why Product Starts at 1 Instead of 0
One of the most common beginner mistakes is writing:
int product = 0;
This is incorrect.
Remember the multiplication rule:
Anything × 0 = 0
For example:
0 × 4 = 0
0 × 2 = 0
0 × 1 = 0
0 × 1 = 0
No matter what digits are processed, the product will always remain 0.
Instead, initialize the product as:
int product = 1;
This works because 1 is the identity element of multiplication, just as 0 is the identity element of addition.
This is the same principle used in:
- Factorial calculations
- Power calculations
- Multiplication-based algorithms
Initializing product to 1 allows the multiplication to build correctly as each digit is processed.
Method 2: Using Recursion
Instead of using a loop, we can process one digit at a time recursively.
In this example, two static variables are used to accumulate the running sum and running product across recursive calls.
public class SpyNumberRecursion {
static int sum = 0;
static int product = 1;
static void processDigits(int num) {
if (num == 0) {
return;
}
int digit = num % 10;
sum += digit;
product *= digit;
processDigits(num / 10);
}
public static void main(String[] args) {
int num = 1124;
processDigits(num);
if (sum == product) {
System.out.println("The number is a spy number.");
} else {
System.out.println("The number is not a spy number.");
}
}
}
How This Works
Each recursive call processes exactly one digit.
For the number 1124, the recursive calls occur like this:
processDigits(1124)
↓
processDigits(112)
↓
processDigits(11)
↓
processDigits(1)
↓
processDigits(0)
During each call:
- The current digit is added to
sum. - The same digit is multiplied into
product. - The remaining digits are processed recursively.
When the recursion finishes:
Sum = 8
Product = 8
Since both values are equal, the program identifies 1124 as a spy number.
This solution demonstrates recursive digit processing and follows the same pattern used in several other digit-based problems throughout this series.
Method 3: Printing All Spy Numbers in a Range
To find every spy number within a range, place the spy number check inside a reusable method and call it for every number in the specified range.
public class SpyNumbersInRange {
static boolean isSpy(int num) {
int sum = 0;
int product = 1;
int temp = num;
while (temp != 0) {
int digit = temp % 10;
sum += digit;
product *= digit;
temp /= 10;
}
return sum == product;
}
public static void main(String[] args) {
int start = 1;
int end = 2000;
System.out.println("Spy numbers between " + start + " and " + end + ":");
for (int num = start; num <= end; num++) {
if (isSpy(num)) {
System.out.print(num + " ");
}
}
}
}
Output (Partial)
Spy numbers between 1 and 2000:
1 2 3 4 5 6 7 8 9 1124 1132 1141 1212 1224 1236 ...
Note: The output shown above is partial because there are many spy numbers between 1 and 2000.
How This Works
Instead of checking a single number, the program iterates through every number in the specified range.
For each number:
- The
isSpy()method calculates the digit sum. - It also calculates the digit product during the same loop.
- The method compares both values.
- If they are equal, the number is printed.
This approach avoids duplicating logic and makes the spy number check reusable for any range.
Handling Zero Digits Within a Number
One particularly interesting property of spy numbers involves zero digits.
Suppose a number contains the digit 0.
For example:
1203
Its digit sum is:
1 + 2 + 0 + 3 = 6
Its digit product is:
1 × 2 × 0 × 3 = 0
Notice what happened.
The moment a 0 appears, the entire product immediately becomes 0 because:
Anything × 0 = 0
For a spy number, we require:
Digit Sum == Digit Product
In this example:
6 ≠ 0
Therefore, 1203 is not a spy number.
In fact, numbers containing a zero digit are very unlikely to be spy numbers because:
- The product immediately becomes 0.
- The digit sum usually remains positive.
The only way the sum can also become 0 is if every digit is 0, which is generally not considered a valid positive integer.
Example with a Zero Digit
public class SpyNumberZeroExample {
public static void main(String[] args) {
int num = 1203;
int sum = 0;
int product = 1;
int temp = num;
while (temp != 0) {
int digit = temp % 10;
sum += digit;
product *= digit;
temp /= 10;
}
System.out.println("Sum: " + sum + ", Product: " + product);
System.out.println(
num + (sum == product
? " is a spy number."
: " is not a spy number.")
);
}
}
Output
Sum: 6, Product: 0
1203 is not a spy number.
Why This Happens
Let's examine the multiplication step by step.
1 × 2 = 2
2 × 0 = 0
0 × 3 = 0
Once the multiplication reaches 0, every remaining multiplication also stays 0.
Meanwhile, the digit sum continues normally:
1 + 2 + 0 + 3 = 6
Since:
6 ≠ 0
the number cannot satisfy the spy number condition.
This behavior is not a bug—it is an expected mathematical property of multiplication.
How Java Handles This Internally (Memory Concept)
Understanding what happens internally helps explain why the spy number algorithm is efficient.
Methods 1 and 3
The following variables are primitive int values:
numtempdigitsumproduct
These variables are stored inside the stack frame of the currently executing method.
During each iteration:
digitstores the current extracted digit.sumis updated using addition.productis updated using multiplication.tempis reduced by removing its last digit.
No additional objects are created during this process.
Method 2 (Recursion)
The recursive version behaves slightly differently.
Each call to:
processDigits(num)
creates a new stack frame containing:
- The current value of
num - Local execution information
- The return address
Unlike the iterative version, the recursive solution stores the running totals inside two static fields:
static int sum;
static int product;
These variables belong to the class rather than to individual method calls, allowing every recursive call to update the same running totals.
After the recursion reaches the base case, the stack frames are removed one by one until execution returns to main().
Heap Memory Usage
None of these implementations create objects dynamically while processing the digits.
There are:
- No arrays
- No collections
- No wrapper objects
- No heap allocations during the algorithm
The only memory used consists of primitive variables and, in the recursive version, the recursive call stack.
As a result, the spy number check remains both simple and memory-efficient, making it another excellent example of a straightforward digit-manipulation algorithm.
Real-Life Analogy: Two Different Paths Leading to the Same Destination
Imagine two people trying to reach the same destination using completely different routes.
- One person walks, measuring progress by adding the distance covered step by step.
- The other drives, where the overall effect is based on multiplying factors such as speed, fuel efficiency, or travel ratios (for the sake of this analogy).
Although both start from the same place, they usually end up with different total values.
Occasionally, however, both approaches produce exactly the same result.
That is the idea behind a spy number.
The same digits are processed in two completely different ways:
- One calculation adds the digits.
- The other multiplies the digits.
When both calculations produce exactly the same value, the number is called a spy number.
Comparison Table of All Methods
| Method | Uses Extra Memory (Heap)? | Best Used When |
|---|---|---|
| While Loop | ❌ No – uses only primitive variables stored on the stack | Standard implementation, interviews, and production code |
| Recursion | ❌ No heap allocation (uses the call stack) | Demonstrating recursive thinking and recursive digit processing |
| Range-Based Loop | ❌ No | Finding all spy numbers within a specified range |
Best Practices
Following these practices will help you write clean, efficient, and reusable spy number programs.
- Always initialize the product variable to 1, not 0, because 1 is the identity element of multiplication.
- Compute both the digit sum and the digit product in the same loop instead of traversing the digits twice.
- Be aware of the zero-digit behavior. A single 0 digit immediately makes the product 0, making it very difficult for the sum and product to become equal.
- Place the checking logic inside a reusable method such as:
boolean isSpy(int num)
This improves readability and allows the same logic to be reused throughout your program.
- Test your implementation using different categories of inputs:
- Single-digit numbers
- Known spy numbers (such as 1124)
- Numbers containing 0
- Numbers that are not spy numbers
Testing multiple input types helps verify that your implementation works correctly in every situation.
Common Mistakes Beginners Make
Although the algorithm is straightforward, beginners often make a few common mistakes.
1. Initializing Product to 0
One of the most common mistakes is writing:
int product = 0;
Since:
Anything × 0 = 0
every multiplication afterwards also becomes 0, making the algorithm incorrect.
The correct initialization is:
int product = 1;
2. Not Understanding the Zero-Digit Behavior
Many beginners think the program is broken when numbers like:
1203
produce:
Sum = 6
Product = 0
This is expected.
The digit 0 immediately reduces the entire product to 0, which is simply how multiplication works.
3. Processing the Digits Twice
Some implementations first calculate the digit sum and then loop through the digits again to calculate the product.
Although correct, this is unnecessary.
A better approach calculates both values during the same iteration:
sum += digit;
product *= digit;
This avoids traversing the digits twice.
4. Confusing Spy Numbers with Harshad Numbers
These two problems are often confused because both involve digit sums.
However, they are completely different.
| Spy Number | Harshad Number |
|---|---|
| Compares digit sum with digit product | Checks whether the original number is divisible by the digit sum |
| Uses equality | Uses divisibility |
Remembering this distinction prevents unnecessary implementation mistakes.
5. Not Testing Single-Digit Numbers
Every positive single-digit number is automatically a spy number because:
Digit Sum = Digit Product
Testing values from 1 through 9 is an excellent way to verify that your implementation behaves correctly before trying larger numbers.
Expert Tips for Interviews
A strong interview answer explains both the algorithm and the reasoning behind it.
A complete answer might sound like this:
"A spy number is a number whose digit sum equals its digit product. I calculate both values simultaneously using modulus and division so that each digit is processed only once. I initialize the product to 1 because 1 is the identity element of multiplication. I'd also mention that numbers containing a zero digit almost always fail the spy number condition because the product immediately becomes zero while the digit sum usually remains positive."
Mentioning the zero-digit behavior without being prompted demonstrates attention to detail and shows that you understand the mathematical behavior of the algorithm rather than simply memorizing the implementation.
Pros and Cons
While Loop
Pros
- ✅ Very simple and easy to understand
- ✅ Calculates the sum and product in a single traversal
- ✅ Efficient and suitable for interviews
- ✅ Uses only primitive variables
Cons
- ❌ No significant drawbacks for this problem
- ❌ Slightly less reusable unless wrapped inside a separate method
Recursion
Pros
- ✅ Demonstrates recursive thinking
- ✅ Reuses familiar recursive digit-processing techniques
- ✅ Good practice for recursion-based problems
Cons
- ❌ Uses static variables in this implementation
- ❌ Requires careful resetting of static fields before reuse
- ❌ Uses additional stack frames due to recursive calls
Frequently Asked Questions (FAQs)
1. What is a spy number?
A spy number is a number whose sum of digits is equal to the product of its digits.
For example, consider 1124.
Digit sum:
1 + 1 + 2 + 4 = 8
Digit product:
1 × 1 × 2 × 4 = 8
Since both values are equal, 1124 is a spy number.
2. What is the simplest example of a spy number?
Every single-digit number (0–9) is a spy number because the sum and product of a single digit are both equal to the digit itself.
The simplest multi-digit spy number is:
1124
because:
1 + 1 + 2 + 4 = 8
1 × 1 × 2 × 4 = 8
3. How do I check if a number is a spy number in Java?
Calculate both the digit sum and the digit product while extracting the digits.
Then compare the two values.
int sum = 0;
int product = 1;
while (num != 0) {
int digit = num % 10;
sum += digit;
product *= digit;
num /= 10;
}
if (sum == product) {
System.out.println("Spy Number");
}
4. Why should I initialize the product variable to 1 instead of 0?
Because 1 is the identity element of multiplication.
If you initialize:
int product = 0;
then every multiplication becomes:
0 × digit = 0
and the product will always remain zero.
Initializing with 1 allows the multiplication to work correctly.
5. What happens if a number contains a 0 digit?
The moment a 0 digit is encountered, the entire product becomes 0.
For example:
1203
Sum = 1 + 2 + 0 + 3 = 6
Product = 1 × 2 × 0 × 3 = 0
Since:
6 ≠ 0
the number is not a spy number.
This is expected behavior because multiplying by zero always produces zero.
6. What is the difference between a spy number and a Harshad number?
Although both problems involve digit manipulation, they use different conditions.
| Spy Number | Harshad Number |
|---|---|
| Compares the sum of digits with the product of digits | Checks whether the original number is divisible by the sum of its digits |
| Uses equality | Uses divisibility |
| Example: 1124 | Example: 18 |
7. Can I check for spy numbers using recursion?
Yes.
Instead of using a loop, you can recursively process one digit at a time while maintaining a running sum and product.
After processing every digit, simply compare the two values.
8. What is the time complexity of checking a spy number?
The time complexity is:
O(d)
where d is the number of digits.
Each digit is processed exactly once.
The space complexity is:
- O(1) for the iterative solution.
- O(d) for the recursive solution because of the recursive call stack.
9. Are spy numbers common or rare?
Single-digit spy numbers are common because every single digit satisfies the condition.
However, multi-digit spy numbers are relatively rare, since requiring the digit sum and digit product to be exactly equal is a fairly restrictive condition.
10. How do I find all spy numbers within a given range in Java?
Loop through every number in the range and call a reusable method such as isSpy().
If the method returns true, print the number.
For example:
for (int num = start; num <= end; num++) {
if (isSpy(num)) {
System.out.print(num + " ");
}
}
This approach allows you to generate all spy numbers within any range.
11. Is checking for a spy number a common interview question?
It is less common than questions about prime numbers, Armstrong numbers, or palindromes, but it still appears in interviews involving digit manipulation.
Interviewers often use it to assess:
- Looping
- Modulus and division operations
- Digit extraction
- Code efficiency
- Understanding of mathematical logic
Mentioning the single-pass calculation and the zero-digit behavior can strengthen your interview answer.
12. Why does calculating the sum and product together in one loop improve efficiency?
Because every digit is processed only once.
Instead of writing two separate loops:
- One for calculating the sum
- Another for calculating the product
you can update both values during the same iteration:
sum += digit;
product *= digit;
This reduces unnecessary work and keeps the implementation simple and efficient.