Подтвердите номер кредитной карты, используя алгоритм Luh
У меня есть вопрос относительно следующего назначения программирования.
Номера кредитных карт соответствуют определенным схемам. Кредитная карта должна содержать от 13 до 16 цифр. Это должно начаться с:
• 4 для карт Visa
• 5 для мастер-карт
• 37 для карт American Express
В 1954 году Ханс Лун из IBM предложил алгоритм проверки номеров кредитных карт. Алгоритм полезен для определения того, правильно ли введен номер карты или правильно ли сканируется кредитная карта сканером. Почти все номера кредитных карт генерируются после этой проверки действительности, обычно известной как проверка Луна или проверка модуля 10, которая может быть описана следующим образом. Для иллюстрации рассмотрим номер карты 4388576018402625.
- Удваивайте каждую вторую цифру справа налево. Если в результате удвоения цифры получается двузначное число, сложите две цифры, чтобы получить однозначное число.
2 х 2 = 4
2 х 2 = 4
4 х 2 = 8
1 х 2 = 2
6 х 2 = 12 (1 + 2 = 3)
5 х 2 = 10 (1 + 0 = 1)
8 х 2 = 16 (1 + 6 = 7)
4 х 2 = 8
Добавьте все однозначные числа из шага 1 4 + 4 +8 + 2 +3 + 1 + 7 + 8 = 37
Добавьте все цифры в нечетных местах справа налево в номере карты
5 + 6 + 0 + 8 + 0 + 7 + 8 + 3 = 37
Суммируйте результаты из шага 2 и шага 3 37 + 37 = 74
Если результат шага делится на 10, номер карты действителен; в противном случае это недействительно. Например, номер 4388576018402625 недействителен, но номер 4388576018410707 является действительной картой Visa; номер 6011000593748745 недействителен, но номер 6011000593748746 является действительной картой обнаружения.
Я попытался решить это, как показано в следующем коде:
import java.util.Scanner;
public class CreditCardValidation {
public static boolean isValid(long number) {
int total = sumOfDoubleEvenPlace(number) + sumOfOddPlace(number);
if ((total % 10 == 0) && (prefixMatched(number, 1) == true) && (getSize(number)>=13 ) && (getSize(number)<=16 )) {
return true;
} else {
return false;
}
}
public static int getDigit(int number) {
if (number <= 9) {
return number;
} else {
int firstDigit = number % 10;
int secondDigit = (int) (number / 10);
return firstDigit + secondDigit;
}
}
public static int sumOfOddPlace(long number) {
int result = 0;
while (number > 0) {
result += (int) (number % 10);
number = number / 100;
}
return result;
}
public static int sumOfDoubleEvenPlace(long number) {
int result = 0;
long temp = 0;
while (number > 0) {
temp = number % 100;
result += getDigit((int) (temp / 10) * 2);
number = number / 100;
}
return result;
}
public static boolean prefixMatched(long number, int d) {
if ((getPrefix(number, d) == 4)
|| (getPrefix(number, d) == 5)
|| (getPrefix(number, d) == 3)) {
if (getPrefix(number, d) == 3) {
System.out.println("\nVisa Card ");
} else if (getPrefix(number, d) == 5) {
System.out.println("\nMaster Card ");
} else if (getPrefix(number, d) == 3) {
System.out.println("\nAmerican Express Card ");
}
return true;
} else {
return false;
}
}
public static int getSize(long d) {
int count = 0;
while (d > 0) {
d = d / 10;
count++;
}
return count;
}
public static long getPrefix(long number, int k) {
if (getSize(number) < k) {
return number;
} else {
int size = (int) getSize(number);
for (int i = 0; i < (size - k); i++) {
number = number / 10;
}
return number;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a credit card number as a long integer: ");
long input = sc.nextLong();
if (isValid(input) == true) {
System.out.println("\n" + input + " is Valid. ");
} else {
System.out.println("\n" + input + " is Invalid. ");
}
}
}
У меня вопрос, как я могу использовать массив для хранения номера кредитной карты вместо длинного номера.
5 ответов
Ладно, это можно решить с помощью преобразования типов в строку и некоторых вещей в Java 8. Не забывайте, что цифры и символы, представляющие числа, не совпадают. '1'!= 1
public static int[] longToIntArray(long cardNumber){
return Long.toString(cardNumber).chars()
.map(x -> x - '0') //converts char to int
.toArray(); //converts to int array
}
Теперь вы можете использовать этот метод для выполнения алгоритма Луна:
public static int luhnCardValidator(int cardNumbers[]) {
int sum = 0, nxtDigit;
for (int i = 0; i<cardNumbers.length; i++) {
if (i % 2 == 0)
nxtDigit = (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : nxtDigit * 2;
sum += nxtDigit;
}
return (sum % 10);
}
Это реализация алгоритма Луна, которую я использую только для 16-значного номера кредитной карты
if(ccnum.length()==16){
char[] c = ccnum.toCharArray();
int[] cint = new int[16];
for(int i=0;i<16;i++){
if(i%2==1){
cint[i] = Integer.parseInt(String.valueOf(c[i]))*2;
if(cint[i] >9)
cint[i]=1+cint[i]%10;
}
else
cint[i] = Integer.parseInt(String.valueOf(c[i]));
}
int sum=0;
for(int i=0;i<16;i++){
sum+=cint[i];
}
if(sum%10==0)
result.setText("Card is Valid");
else
result.setText("Card is Invalid");
}else
result.setText("Card is Invalid");
Если вы хотите использовать его на любом номере, замените все 16 длиной вашего введенного номера.
Это будет работать для номера Visa, указанного в вопросе.(Я проверял это)
Вот моя реализация формулы Луна.
/**
* Runs the Luhn Equation on a user inputed CCN, which in turn
* determines if it is a valid card number.
* @param c A user inputed CCN.
* @param cn The check number for the card.
* @return If the card is valid based on the Luhn Equation.
*/
public boolean luhn (String c, char cn)
{
String card = c;
String checkString = "" + cn;
int check = Integer.valueOf(checkString);
//Drop the last digit.
card = card.substring(0, ( card.length() - 1 ) );
//Reverse the digits.
String cardrev = new StringBuilder(card).reverse().toString();
//Store it in an int array.
char[] cardArray = cardrev.toCharArray();
int[] cardWorking = new int[cardArray.length];
int addedNumbers = 0;
for (int i = 0; i < cardArray.length; i++)
{
cardWorking[i] = Character.getNumericValue( cardArray[i] );
}
//Double odd positioned digits (which are really even in our case, since index starts at 0).
for (int j = 0; j < cardWorking.length; j++)
{
if ( (j % 2) == 0)
{
cardWorking[j] = cardWorking[j] * 2;
}
}
//Subtract 9 from digits larger than 9.
for (int k = 0; k < cardWorking.length; k++)
{
if (cardWorking[k] > 9)
{
cardWorking[k] = cardWorking[k] - 9;
}
}
//Add all the numbers together.
for (int l = 0; l < cardWorking.length; l++)
{
addedNumbers += cardWorking[l];
}
//Finally, check if the number we got from adding all the other numbers
//when divided by ten has a remainder equal to the check number.
if (addedNumbers % 10 == check)
{
return true;
}
else
{
return false;
}
}
Я передаю в карточку как c
который я получаю со сканера и храню в card
, и для cn
Я прохожу checkNumber = card.charAt( (card.length() - 1) );
,
Есть два способа разделить ваш int
в List<Integer>
- использование
%10
как вы используете и сохраните его вList
- Преобразовать в
String
а затем принять числовые значения
Вот пара быстрых примеров
public static void main(String[] args) throws Exception {
final int num = 12345;
final List<Integer> nums1 = splitInt(num);
final List<Integer> nums2 = splitString(num);
System.out.println(nums1);
System.out.println(nums2);
}
private static List<Integer> splitInt(int num) {
final List<Integer> ints = new ArrayList<>();
while (num > 0) {
ints.add(0, num % 10);
num /= 10;
}
return ints;
}
private static List<Integer> splitString(int num) {
final List<Integer> ints = new ArrayList<>();
for (final char c : Integer.toString(num).toCharArray()) {
ints.add(Character.getNumericValue(c));
}
return ints;
}
public class Creditcard {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
String cardno = sc.nextLine();
if(checkType(cardno).equals("U")) //checking for unknown type
System.out.println("UNKNOWN");
else
checkValid(cardno); //validation
}
private static String checkType(String S)
{
int AM=Integer.parseInt(S.substring(0,2));
int D=Integer.parseInt(S.substring(0,4)),d=0;
for(int i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
d++;
}
if((AM==34 || AM==37) && d==15)
System.out.println("AMEX");
else if(D==6011 && d==16)
System.out.println("Discover");
else if(AM>=51 && AM<=55 && d==16)
System.out.println("MasterCard");
else if(((S.charAt(0)-'0')==4)&&(d==13 || d==16))
System.out.println("Visa");
else
return "U";
return "";
}
private static void checkValid(String S) // S--> cardno
{
int i,d=0,sum=0,card[]=new int[S.length()];
for(i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
card[d++]=S.charAt(i)-'0';
}
for(i=0;i<d;i++)
{
if(i%2!=0)
{
card[i]=card[i]*2;
if(card[i]>9)
sum+=digSum(card[i]);
else
sum+=card[i];
}
else
sum+=card[i];
}
if(sum%10==0)
System.out.println("Valid");
else
System.out.println("Invalid");
}
public static int digSum(int n)
{
int sum=0;
while(n>0)
{
sum+=n%10;
n/=10;
}
return sum;
}
}