40 lines
1.1 KiB
Lua
40 lines
1.1 KiB
Lua
-- implementation of Luhn's checksum algorithm, computing and checking of checksum digit
|
|
local luhn = {}
|
|
|
|
-- main part of the algorithm, double each 2 digits, clamp them and return the sum.
|
|
function luhn:_sum_digits(num)
|
|
assert(num >= 0, "number must be positive")
|
|
local sum = 0
|
|
local digits_n = 0
|
|
|
|
repeat -- iterate over digits from right to left
|
|
local tmp = num % 10 -- get current unit
|
|
-- each 2 digits, double the current digit
|
|
if (digits_n % 2) == 0 then tmp = tmp * 2 end
|
|
if tmp > 9 then tmp = tmp - 9 end
|
|
|
|
digits_n = digits_n + 1
|
|
sum = sum + tmp
|
|
-- remove unit from number
|
|
num = math.floor(num / 10)
|
|
until num == 0
|
|
return sum
|
|
end
|
|
|
|
-- returns the computed check digit
|
|
function luhn:compute_check_digit(num)
|
|
return (self:_sum_digits(num) * 9) % 10
|
|
end
|
|
|
|
-- returns true if its valid, false otherwise
|
|
function luhn:validate_check_digit(num)
|
|
local check_digit = num % 10 -- get check digit
|
|
return self:compute_check_digit(math.floor(num / 10)) == check_digit
|
|
end
|
|
|
|
-- returns the original number with the check digit concatenated at the end
|
|
function luhn:make_number(num)
|
|
return ((num * 10) + self:compute_check_digit(num))
|
|
end
|
|
|
|
return luhn
|