This MySQL function should generate a check digit using Luhn algorithm. Given the number 345722 the function should return 3. It returns 6 which is wrong.
drop function if exists luhn;
delimiter //
create function luhn(myNum varchar(20))
returns varchar(1)
sql security invoker
begin
declare sIndex, digit, len, parity,SumX int;
set myNum=concat(myNum,'0');
set len = length(myNum);
set parity = len % 2;
set SumX =0;
set sIndex = len - 1;
while sIndex >= 0 do
set digit = substring(myNum, sIndex,1);
if(sIndex % 2 = parity) then set digit = digit * 2;
end if;
if(digit > 9) then set digit = digit - 9;
end if;
set SumX = SumX + digit;
set sIndex = sIndex - 1;
end while;
if SumX % 10 =0 then return 0;
else return (10 - (SumX % 10));
end if;
end //
delimiter;
I converted the code above from the PHP code below which works.
function luhn_checksum($myNum) {
$myNum = $myNum . "0";
$len = strlen($myNum);
$parity = $len % 2;
$sum = 0;
for ($index = $len - 1; $index >= 0; $index--) {
$digit = intval($myNum[$index]);
if ($index % 2 == $parity) {
$digit *= 2;
}
if ($digit > 9) {
$digit -= 9;
}
$sum += $digit;
}
if($sum % 10===0){return(0);}
$finalCheckDigit= 10-($sum % 10);
return($finalCheckDigit);
}
Given the number on the left I am expecting the middle number but getting the number on the right.
input expect returned
371950 7 5
367489 2 3
367457 9 1
350684 7 2
347772 6 1
345722 3 6
343464 4 3
339403 8 5
337069 9 4
331979 5 6
330500 0 6
I using this page to validate https://simplycalc.com/luhn-calculate.php
Unless you are running your Luhn check-digit generation against a large dataset, these performance differences are not really relevant, but it has kept me entertained for a bit.
Some small performance enhancements to Bill's answer:
0+
to implicitly cast to integer is unnecessary, asdigit
is declared asint
set
statements into one is just a bit faster, albeit reducing readabilityHere's another approach without using a loop, which is a bit faster:
And here's another version, specifically optimised for an input of 6 chars:
Unsurprisingly, they all produce the same output:
Using benchmark to run 1M iterations, I got the following execution times: