Simplification
- You can simplify your return condition. When you break from your loop it is either because the quotient equals 0 or the digit sum is greater than the candidate number. If the quotient is nonzero then the digit sum must be greater than the candidate. Therefore, all you need to do is
return (digitSum == candidate)
.
Math
As is mentioned in another answer there is no need for multiplyExact
. Even a 10-bit number can store the result of any cubed digit. So unless your long is less than 10-bit you should be ok.
My first thought would be maybe we need addExact
not multiplyExact
. However we can show that addExact
is most likely not needed either. We can always represent the candidate
within a long
by definition. Let \$n\$ represent this candidate value. The question we need to answer is when is the digit sum greater than \$n\$, i.e. when is there a chance for us to overflow the long
when performing the digit sum?
This question isn't so easy to answer. But we can answer an easier question: When does a \$m\$-digit number have at most an \$m-1\$ digit cube digit sum?
The best case is that the \$m\$-digit number is composed only of \$9\$.
$$ m \cdot 9^3 \leq 10^{m-1} - 1$$
$$ 9^3 \leq \frac{10^{m-1} - 1}{m}$$
The right side of the inequality is monotonically increasing on \$[1, \infty)\$ in both the continuous and discrete domain. In the discrete world, you can see this by changing the value from \$m=i\$ to \$m=i+1\$ which increases the numerator by more than 10 and the denominator by at most 2. Anyway, we get equality if \$m \approx 4.51778\$. So for any number with 5 or more digits, the sum cannot overflow. The same argument shows that any number with 5 or more digits cannot satisfy your definition of an Armstrong number either.
Performance
Scalability is always what I look for in problems like this. Yes a long
may not be that big these days but why limit ourselves with inferior algorithms that do not scale well?
Consider you have the number $$n = 123456789012345678901234567890...$$
Let's just say this number has \$m\$ digits. You will end up performing \$2m\$ multiplications and \$m-1\$ additions. However, of those multiplications, you can only have \$10\$ unique values since there are only \$10\$ digits. You should therefore pre-compute the powers so that you do not have to recompute them over and over.
final static long[] cubes = { 0, 1, 8, 27, 64, 125, 216, 343, 512, 729 };
public static boolean isArmstrong(long candidate)
{
long sum = 0;
long n = candidate;
while( n > 0 && sum <= candidate )
{
long digit = n % 10;
n = n / 10;
sum += cubes[(int)digit];
}
return (sum == candidate);
}