用java8流计算Luhn算法
我正试图借助Java8中的流API验证一个数字用java8流计算Luhn算法,java,algorithm,java-8,java-stream,Java,Algorithm,Java 8,Java Stream,我正试图借助Java8中的流API验证一个数字 private void ValidateIMEI() { field //a field holding an IMEI Number .getText().chars() .map(this::ConvertASCIIToNumer); } 我被卡住的部分是将偶数加倍,然后除以10 最初,我尝试了传统的for循环: private void ValidateIMEI() { in
private void ValidateIMEI() {
field //a field holding an IMEI Number
.getText().chars()
.map(this::ConvertASCIIToNumer);
}
我被卡住的部分是将偶数加倍,然后除以10
最初,我尝试了传统的for循环:
private void ValidateIMEI() {
int[] numbers = field //a field holding an IMEI Number
.getText().chars()
.map(this::ConvertASCIIToNumer).toArray();
int sum = 0;
for (int i = 0; i < numbers.length; i++) {
//Double the even number and divide it by 10. add quotient and remainder
if ((numbers[i]+1) % 2 == 0) {
numbers[i] = numbers[i] * 2;
numbers[i] = numbers[i] / 10 + numbers[i] % 10;
}
sum += numbers[i];
}
if (sum%10==0) {
status.setText("Valid");
}
else{
status.setText("InValid");
}
}
您的错误是,当您应该将索引为偶数的数字加倍时,您将偶数加倍。由于索引在这个算法中很重要,我建议使用
IntStream
索引:
boolean isValid =
IntStream.range(0,numbers.length)
.map (i -> (((i%2) ^ (numbers.length%2)) == 0) ? ((2*numbers[i])/10+(2*numbers[i])%10) : numbers[i])
.sum() % 10 == 0;
编辑:我刚刚更改了条件,因为数组的长度决定了奇数索引还是偶数索引应该乘以2
如果数组的长度为偶数,则偶数索引中的数字应加倍:
Index 0 1 2 3 4 5
Digit 1 5 2 5 2 6
- - -
如果数组长度为奇数,则奇数索引中的数字应为两位数:
Index 0 1 2 3 4
Digit 1 5 2 5 2
- -
这是我能做的最漂亮的:
String num; // your IMEI number
int[] a = {num.length() % 2 == 0 ? 1 : 2}; // 1 if length even, 2 otherwise
boolean isLuhn = num.chars()
.map(i -> i - '0') // convert to the int equivalent
.map(n -> n * (a[0] = a[0] == 1 ? 2 : 1)) // multiply by 1, 2 alternating
.map(n -> n > 9 ? n - 9 : n) // handle sum of digits
.sum() % 10 == 0; // mod 10 should be zero
这里使用的“技巧”是使用
int[]
,而不是int
,变量来保存乘数。这是一种仅允许引用“有效最终”变量的变通方法;数组引用实际上是最终的,但是它的内容(只有一个元素)不是必须的 woha int无法转换为布尔值。我将把a^b==0替换为a==b。或者,您只能迭代到数字数组长度的一半,并在每次迭代中处理一对数字。@RiaD或(i-numbers.length())%2==0
。(我知道,对于负数I
s和非常长的数组,这会溢出,但我们碰巧知道,在我们的例子中,这两种情况都不正确。)当您实际需要char
s时,不需要拆分为字符串。换句话说,不要使用Arrays.stream(num.split(“”)
。您只需要num.chars().map(c->c-'0')
…@Holger omg。。。一直以来,我都没有注意到这种方法。感谢您的课程:)第一个.map()
中的i
与上面定义的变量int[]i
冲突。我收到以下错误:Lambda表达式的参数我无法重新声明在封闭范围中定义的另一个局部变量。
@maxyme-Ah。我现在修好了。(我通常手边没有编译器,因为我的大部分代码都是通过手机输入的)
String num; // your IMEI number
int[] a = {num.length() % 2 == 0 ? 1 : 2}; // 1 if length even, 2 otherwise
boolean isLuhn = num.chars()
.map(i -> i - '0') // convert to the int equivalent
.map(n -> n * (a[0] = a[0] == 1 ? 2 : 1)) // multiply by 1, 2 alternating
.map(n -> n > 9 ? n - 9 : n) // handle sum of digits
.sum() % 10 == 0; // mod 10 should be zero