Luhn algorithm in PHP

As I mentioned before, the Luhn algorithm is used to validate some interesting numbers, most notably GSM IMEIs and credit card numbers. Here’s another implementation I wrote, this time in PHP.

	function luhn($str) {
		$odd = !strlen($str)%2;
		$sum = 0;
		for($i=0;$i<strlen($str);++$i) {
			$n=0+$str&#91;$i&#93;;
			$odd=!$odd;
			if($odd) {
				$sum+=$n;
			} else {
				$x=2*$n;
				$sum+=$x>9?$x-9:$x;
			}
		}
		return(($sum%10)==0);
	}

(Download)

7 thoughts on “Luhn algorithm in PHP”

  1. I think you’ve got a little error there; you’ve got your even/odd reversed:
    function luhn($str) {
    $odd = !strlen($str)%2;
    $sum = 0;
    for($i=0;$i9?$x-9:$x;
    }
    $odd=!$odd;
    }
    return(($sum%10)==0);
    }

  2. *heheh* Well, there’s a double negative in there, and I admit that it is kind of confusing at first glance. Be assured that the implementation works as intended. You might want to take a look to the Demo for the Luhn Algorithm in PHP to check out some numbers and see that it does work.

  3. heres a better one:

    function luhn($s) {
    $sum=0;
    $res=preg_match(“/[0-9]{14,16}/”,str_replace(“-“,””,$s),$s);
    if ($res==0) { return false; }
    $s=$s[0];
    $i=strlen($s);
    while ($i–>=0) {
    $sum+=(($i%2)==0)?(($s[$i]*2)>9)?(($s[$i]*2)-9):($s[$i]*2):$s[$i];
    }
    return (($sum%10)==0);
    }

  4. What the Hell, $str? $str%2 is a methematical operation, the complete operations are mathematical, the parameter has to be named $int, all creditcards use integer values.
    Before you can start anything, please validate the data.
    Strip spaces convert to int or use explizit typehinding.
    Since php5 return exceptions or since php4 raise or return an error objekt so the programmer will receive informations about what is making trouble with this “number”.

    And what will this do? $n = 0+$str[$i]; ???

    Beside of this little Semantik mistakes i will thank you alot for this, it has be avoked alot of work for me, thanks very much.

  5. @Anthony
    >> You?re making an assumption that the card will be 14-16 characters long.

    The function works with 14-16 cc numbres, and returns false if the cc is not in this range. He does not do any assumptions, the cc must be 14-16 or won’t be validated.

    @dbl
    >> What the Hell, $str? $str%2 is a methematical operation, the complete operations are
    >> mathematical, the parameter has to be named $int, all creditcards use integer values.

    By the looks of it, your experience with php is limited.

    The function takes a string with the text representation of the credit card number, and all operations are made on this string.

    $str is a string, so i can’t imagine why you’d like to call it “$int”.

    >> And what will this do? $n = 0+$str[$i]; ???

    Force the conversion of $str to a number. Any math operations involving string and numbers on php results on a number, as string conversion is automatically done in the scope of the expression.

    $str = “10.4”;
    $float = 0+$str;

    Now $float contains a floating point number instead of a string.

    “If the string does not contain any of the characters ‘.’, ‘e’, or ‘E’ and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.”

    http://php.net/manual/en/language.types.string.php#language.types.string.syntax.nowdoc

  6. @limpc: You have an error in regex, you are only checking that 14-16 digits EXIST in $s, not that $is is made of 14-16 digits. A better way would be:
    if (0==preg_match(‘/^[0-9]{14,16}$/’,str_replace(‘-‘,”,$s),$s))
    return(false);
    Note the use of single quotes – it would not be a good idea to use dollar sign with double quotes (without escaping it).

    @javier, Iago: while the original function (probably) works it is also very difficult to understand and would thus better be avoided. For instance, ‘0+$str[$i]’ works, but a more readable way would be ‘(int)$str[$i]’. Both statements do the same, but there is no question about the purpose of the second one. But nice of you to publish it nevertheless. I like the idea of $x-9, nice. :)

    Here is my try to make it cleaner:

    function luhn_validate($str)
    {
    // let’s add regex – at least two digits, only digits or ‘-‘ allowed:
    if (0==preg_match(‘/^[0-9][0-9]+$/’,str_replace(‘-‘,”,$s),$s))
    return(false);

    $sum=0;
    for ($i=0;$i9)?($x-9):($x);
    }
    else // 0,2,4,…
    $sum+=$n;
    }
    return(($sum%10)==0);
    }

    Enjoy!

Comments are closed.