1. Overview
1.概述
In this quick tutorial, we’ll learn what Armstrong numbers are and how to check and find them by creating a Java program.
在这个快速教程中,我们将学习什么是阿姆斯特朗数字,以及如何通过创建一个Java程序来检查和找到它们。
2. Introduction to the Problem
2.对问题的介绍
First, let’s understand what an Armstrong number is.
首先,让我们了解一下什么是阿姆斯特朗数字。
Given a positive integer i of n digits, the integer i is an Armstrong number if the sum of the n-th powers of their digits is equal to i. Armstrong numbers form the OEIS sequence A005188.
给定一个正整数i的n位,如果nth其位数的幂等于i,则该整数i是一个阿姆斯特朗数。阿姆斯特朗数构成OEIS sequence A005188.
A few examples may help us understand Armstrong numbers quickly:
几个例子可能有助于我们快速理解阿姆斯特朗的数字。
- 1: pow(1,1) = 1 -> 1 is an Armstrong number.
- 123: pow(1, 3) + pow(2, 3) + pow(3, 3) = 1 + 8 +27 = 36 != 123 -> 123 is not an Armstrong number.
- 1634: pow(1, 4) + pow(6, 4) + pow(3, 4) + pow(4, 4) = 1 + 1296 + 81 + 256 = 1643 -> 1634 is an Armstrong number.
So, we want to have a Java program to conveniently check if a given number is an Armstrong number. Further, we’d like to produce an OEIS sequence A005188 less than a given limit.
因此,我们希望有一个Java程序来方便地检查一个给定的数字是否是阿姆斯特朗数字。此外,我们想产生一个小于给定限制的OEIS序列A005188。
For simplicity, we’ll use unit test assertions to verify whether our methods work as expected.
为了简单起见,我们将使用单元测试断言来验证我们的方法是否按预期工作。
3. The Idea to Solve the Problem
3.解决问题的想法
Now that we understand Armstrong numbers let’s look into the problem and consider the idea to solve it.
现在我们了解了阿姆斯特朗的数字,让我们来研究一下这个问题,并考虑解决这个问题的想法。
First, generating an OEIS sequence A005188 with a limit can be translated into going from 0 to the given limit and finding out all Armstrong numbers. If we’ve a method to check if an integer is an Armstrong number, it’s easy to filter out non-Armstrong numbers from the integer range and get the desired sequence.
首先,生成一个有极限的OEIS序列A005188可以转化为从0到给定的极限,并找出所有的阿姆斯特朗数字。如果我们有一个方法来检查一个整数是否是阿姆斯特朗数字,就很容易从整数范围内过滤掉非阿姆斯特朗数字,得到想要的序列。
Thus, the primary problem is to create the Armstrong number check method. A straightforward idea to do the check is a two-step approach:
因此,首要问题是建立阿姆斯特朗数字检查方法。做检查的一个直接的想法是两步法。
- step 1 – break the given integer into a digit list, for instance, 12345 -> [1, 2, 3, 4, 5]
- step 2 – for each digit in the list, calculate pow(digit, list.size()), then sum the results, and finally compare the sum to the initially given integer
Next, let’s convert the idea into Java code.
接下来,让我们把这个想法转换成Java代码。
4. Creating Armstrong Number Methods
4.创建阿姆斯特朗数字方法
As we’ve discussed, let’s first convert the given integer to a digit list:
正如我们已经讨论过的,首先让我们把给定的整数转换成数字列表。
static List<Integer> digitsInList(int n) {
List<Integer> list = new ArrayList<>();
while (n > 0) {
list.add(n % 10);
n = n / 10;
}
return list;
}
As the code above shows, we extract digits from n in a while loop. In each step, we take one digit through n % 10, then shrink the number by n = n / 10.
如上面的代码所示,我们在一个while循环中从n中提取数字。在每一步中,我们通过n % 10抽取一个数字,然后通过n = n / 10缩小数字。
Alternatively, we can convert the number into a string and use the split() method to get a digit-in-string list. Then, finally, we can convert each digit back to an integer again. Here, we haven’t taken this approach.
另外,我们可以将数字转换成字符串,并使用split()方法来获得一个字符串中的数字列表。然后,最后,我们可以将每个数字再次转换为整数。在这里,我们没有采取这种方法。
Now that we’ve created the check method, we can move to step 2: pow() calculation and sum:
现在我们已经创建了检查方法,我们可以进入第二步:pow()计算和总结。
static boolean isArmstrong(int n) {
if (n < 0) {
return false;
}
List<Integer> digitsList = digitsInList(n);
int len = digitsList.size();
int sum = digitsList.stream()
.mapToInt(d -> (int) Math.pow(d, len))
.sum();
return n == sum;
}
As we can see in the isArmstrong() check method, we’ve used Java Stream‘s mapToInt() method to turn each digit into the result after the pow() calculation and then sum the results in the list.
正如我们在isArmstrong() 检查方法中看到的,我们使用了Java Stream的mapToInt()方法,将每个数字变成pow()计算后的结果,然后sum列表中的结果。
Finally, we compared the sum to the initial integer to determine if the number is an Armstrong number.
最后,我们将总和与初始整数进行比较,以确定该数字是否为阿姆斯特朗数字。
It’s worth mentioning that we can alternatively combine the mapToInt() and the sum() method calls into one reduce() call:
值得一提的是,我们可以选择将mapToInt()和sum()方法调用合并为一个reduce()调用。
int sum = digits.stream()
.reduce(0, (subtotal, digit) -> subtotal + (int) Math.pow(digit, len));
Next, let’s create a method to generate the OEIS sequence A005188 up to a limit:
接下来,让我们创建一个方法来生成OEIS序列A005188,直到一个极限。
static List<Integer> getA005188Sequence(int limit) {
if (limit < 0) {
throw new IllegalArgumentException("The limit cannot be a negative number.");
}
return IntStream.range(0, limit)
.boxed()
.filter(ArmstrongNumberUtil::isArmstrong)
.collect(Collectors.toList());
}
As we can see in the code above, we’ve used Stream API again to filter Armstrong numbers and generate the sequence.
正如我们在上面的代码中所看到的,我们再次使用Stream API来过滤Armstrong数字并生成序列。
5. Testing
5.测试
Now, let’s create some tests to verify if our methods work as expected. First, let’s start with some test data:
现在,让我们创建一些测试,以验证我们的方法是否按预期工作。首先,让我们从一些测试数据开始。
static final Map<Integer, Boolean> ARMSTRONG_MAP = ImmutableMap.of(
0, true,
1, true,
2, true,
153, true,
370, true,
407, true,
42, false,
777, false,
12345, false);
Now, let’s pass each number in the Map above to our check method and see if returns the expected result:
现在,让我们把上面Map中的每个数字传递给我们的检查方法,看看是否返回预期结果。
ARMSTRONG_MAP.forEach((number, result) -> assertEquals(result, ArmstrongNumberUtil.isArmstrong(number)));
If we run the test, it passes. So, the check method does the job correctly.
如果我们运行这个测试,它就会通过。所以,检查方法正确地完成了工作。
Next, let’s prepare two expected sequences and test if getA005188Sequence() works as expected too:
接下来,让我们准备两个预期的序列,并测试getA005188Sequence()是否也能像预期那样工作。
List<Integer> A005188_SEQ_1K = ImmutableList.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407);
List<Integer> A005188_SEQ_10K = ImmutableList.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474);
assertEquals(A005188_SEQ_1K, ArmstrongNumberUtil.getA005188Sequence(1000));
assertEquals(A005188_SEQ_10K, ArmstrongNumberUtil.getA005188Sequence(10000));
Our test passes if we give it a run.
如果我们让它运行一下,我们的测试就会通过。
6. Conclusion
6.结语
In this article, we’ve discussed what an Armstrong number is. Further, we’ve created methods to check if an integer is an Armstrong number and generate OEIS sequence A005188 up to a given limit.
在这篇文章中,我们已经讨论了什么是阿姆斯特朗数。此外,我们还创建了一些方法来检查一个整数是否是阿姆斯特朗数,并生成OEIS序列A005188,直到一个给定的限制。
As usual, all code snippets presented here are available over on GitHub.
像往常一样,这里介绍的所有代码片段都可以在GitHub上找到。。