Question

I'm pretty awful at Javascript as I've just started learning. I'm doing a Luhn check for a 16-digit credit card. It's driving me nuts and I'd just appreciate if someone looked over it and could give me some help.

<script>
var creditNum;
var valid = new Boolean(true);

creditNum = prompt("Enter your credit card number: ");

if((creditNum==null)||(creditNum=="")){
    valid = false;
    alert("Invalid Number!\nThere was no input.");
}else if(creditNum.length!=16){
    valid = false;
    alert("Invalid Number!\nThe number is the wrong length.");
}
//Luhn check
var c;
var digitOne;
var digitTwo;
var numSum;
for(i=0;i<16;i+2){
    c = creditNum.slice(i,i+1);
    if(c.length==2){
        digitOne = c.slice(0,1);
        digitTwo = c.slice(1,2);
        numSum = numSum + (digitOne + digitTwo);
    }else{
        numSum = numSum + c;
    }
}
if((numSum%10)!=0){
    alert("Invalid Number!");
}else{
    alert("Credit Card Accepted!");
}
</script>
Was it helpful?

Solution

The immediate problem in your code is your for loop. i+2 is not a proper third term. From the context, you're looking for i = i + 2, which you can write in shorthand as i += 2.

It seems your algorithm is "take the 16 digits, turn them into 8 pairs, add them together, and see if the sum is divisible by 10". If that's the case, you can massively simplify your loop - you never need to look at the tens' place, just the units' place.

Your loop could look like this and do the same thing:

for (i = 1; i < 16; i +=2) {
    numSum += +creditNum[i];
}

Also, note that as long as you're dealing with a string, you don't need to slice anything at all - just use array notation to get each character.

I added a + in front of creditNum. One of the issues with javascript is that it will treat a string as a string, so if you have string "1" and string "3" and add them, you'll concatenate and get "13" instead of 4. The plus sign forces the string to be a number, so you'll get the right result.

The third term of the loop is the only blatant bug I see. I don't actually know the Luhn algorithm, so inferred the rest from the context of your code.

EDIT

Well, it would have helped if you had posted what the Luhn algorithm is. Chances are, if you can at least articulate it, you can help us help you code it.

Here's what you want.

// Luhn check
function luhnCheck(sixteenDigitString) {
    var numSum = 0;
    var value;
    for (var i = 0; i < 16; ++i) {
        if (i % 2 == 0) {
            value = 2 * sixteenDigitString[i];
            if (value >= 10) {
                value = (Math.floor(value / 10) + value % 10);
            }
        } else {
            value = +sixteenDigitString[i];
        }
        numSum += value;
    }
    return (numSum % 10 == 0);
} 

alert(luhnCheck("4111111111111111"));

What this does is go through all the numbers, keeping the even indices as they are, but doubling the odd ones. If the doubling is more than nine, the values of the two digits are added together, as per the algorithm stated in wikipedia.

FIDDLE

Note: the number I tested with isn't my credit card number, but it's a well known number you can use that's known to pass a properly coded Luhn verification.

OTHER TIPS

My below solution will work on AmEx also. I submitted it for a code test a while ago. Hope it helps :)

function validateCard(num){
    var oddSum = 0;
    var evenSum = 0;
    var numToString = num.toString().split("");
    for(var i = 0; i < numToString.length; i++){
      if(i % 2 === 0){
        if(numToString[i] * 2 >= 10){
          evenSum += ((numToString[i] * 2) - 9 );
        } else {
          evenSum += numToString[i] * 2;
        }
      } else {
        oddSum += parseInt(numToString[i]);
      }
    }
    return (oddSum + evenSum) % 10 === 0;
  }
console.log(validateCard(41111111111111111));

Enjoy - Mitch from https://spangle.com.au

@Spangle, when you're using even and odd here, you're already considering that index 0 is even? So you're doubling the digits at index 0, 2 and so on and not the second position, fourth and so on.. Is that intentional? It's returning inconsistent validations for some cards here compared with another algorithm I'm using. Try for example AmEx's 378282246310005.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top