如何实现Luhn算法?

我正在尝试创建一个程序来validation基于luhn算法的10到12位长数字序列,但是我的程序一直告诉我每个数字都是无效的,即使它们不是。

这个数字应该是有效的,但我的代码不这么认为: 8112189876

这个号码不应该是有效的,我的程序同意,因为它认为每个号码都是无效的: 8112189875

这是我的代码:

 static void luhn(){ System.out.print("Enter number to validate:\n"); String pnr = input.nextLine(); int length = pnr.length(); int sum = 0; for (int i = 1, pos = length - 1; i  9) product -= 9; sum+= product; boolean valid = (sum % 10 == 0); if (valid){ System.out.print("Valid!\r"); } else{ System.out.print("Invalid!"); } } } 

我看到的第一件事是你有:

 int num = tmp - 0 

你应该改为:

 int num = tmp - '0'; 

其次,你应该在for循环之外validation你的总和,因为你只关心处理所有数字之后的总和。

第三,您从数字的末尾开始,并且您不包括字符串的第一个数字。 为什么不将i用于这两项任务?

结果(工作)方法:

 static void luhn(){ System.out.print("Enter number to validate:\n"); String pnr = input.nextLine(); // this only works if you are certain all input will be at least 10 characters int extraChars = pnr.length() - 10; if (extraChars < 0) { throw new IllegalArgumentException("Number length must be at least 10 characters!"); } pnr = pnr.substring(extraChars, 10 + extraChars); int sum = 0; // #3: removed pos for (int i = 0; i < pnr.length(); i++){ char tmp = pnr.charAt(i); // #1: fixed the '0' problem int num = tmp - '0'; int product; if (i % 2 != 0){ product = num * 1; } else{ product = num * 2; } if (product > 9) product -= 9; sum+= product; } // #2: moved check outside for loop boolean valid = (sum % 10 == 0); if (valid){ System.out.print("Valid!\r"); } else{ System.out.print("Invalid!"); } } 

从风格上讲 ,如果代替方法签名,这种方法会更有用

 static void luhn() { 

它反而有方法签名

 static boolean luhn(String input) { 

这很容易让你的代码从任何来源(一个文件,硬编码等)获取String ,并对结果做任何事情(打印一条消息,或者做其他事情)。 显然,您将移动System.out.printinput.nextLine()以及此方法之外的if(valid)位代码。

完全重构的程序:

 import java.util.Scanner; public class Luhn { private static Scanner input; public static void main(String... args) { input = new Scanner(System.in); System.out.print("Enter number to validate:\n"); String pnr = input.nextLine(); boolean result = luhn(pnr); printMessage(result); input.close(); } static boolean luhn(String pnr){ // this only works if you are certain all input will be at least 10 characters int extraChars = pnr.length() - 10; if (extraChars < 0) { throw new IllegalArgumentException("Number length must be at least 10 characters!"); } pnr = pnr.substring(extraChars, 10 + extraChars); int sum = 0; for (int i = 0; i < pnr.length(); i++){ char tmp = pnr.charAt(i); int num = tmp - '0'; int product; if (i % 2 != 0){ product = num * 1; } else{ product = num * 2; } if (product > 9) product -= 9; sum+= product; } return (sum % 10 == 0); } private static void printMessage(boolean valid) { if (valid){ System.out.print("Valid!\r"); } else{ System.out.print("Invalid!"); } } } 

使用org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit.LUHN_CHECK_DIGIT.isValid(number)

Maven依赖:

  commons-validator commons-validator 1.5.1  

我在应用程序中使用此function来检查卡号有效性:

 public static boolean Check(String ccNumber) { int sum = 0; boolean alternate = false; for (int i = ccNumber.length() - 1; i >= 0; i--) { int n = Integer.parseInt(ccNumber.substring(i, i + 1)); if (alternate) { n *= 2; if (n > 9) { n = (n % 10) + 1; } } sum += n; alternate = !alternate; } return (sum % 10 == 0); } 

希望能帮助到你,

你应该从tmp减去’0’而不是0.减去0会返回你不想要的ASCII值。