# LuhnCalc and bpay MOD10 version 5 [closed]

Ok so my maths maybe not so good, but here is my question

So I am using the following

<?php
function LuhnCalc($number) {$chars = array_reverse(str_split($number, 1));$odd = array_intersect_key($chars, array_fill_keys(range(1, count($chars), 2), null));
$even = array_intersect_key($chars, array_fill_keys(range(0, count($chars), 2), null));$even = array_map(function($n) { return ($n >= 5)?2 * $n - 9:2 *$n; }, $even);$total = array_sum($odd) + array_sum($even);
return ((floor($total / 10) + 1) * 10 -$total) % 10;
}
print LuhnCalc($_GET['num']); ?> however it seems that BPAY which is version 5 of MOD 10 which for the record I cant find what the documentation for. seems to not be the same as MOD10 the following numbers where tested 2005, 1597, 3651, 0584, 9675 bPAY 2005 = 20052 1597 = 15976 3651 = 36514 0584 = 05840 9675 = 96752 MY CODE 2005 = 20057 1597 = 15974 3651 = 36517 0584 = 05843 9675 = 96752 as you can see none, of them match the BPAY numbers - Could you clarify what your question is - are you asking why two sets of numbers don't come out the same? Should we interpret your tables as having inputs in the left column and outputs in the right? What does your function actually do - for those of us who don't know PHP code - and what is it supposed to do (I'm guessing this)? Also, modules are an algebraic structure in mathematics, and are not really related to modular arithmetic despite the name. – anon Jun 21 '12 at 0:42 (Also posted on SO one week ago: stackoverflow.com/questions/11024309/…) – anon Jun 21 '12 at 0:42 Yes it was posted and was suggested to post it on here, yes I do need the numbers to match and I need to know how to make them match – RussellHarrower Jun 21 '12 at 1:49 If you want to make this a math question and you can generate more checksums yourself, you should generate many more checksums (and if possible related together, e.g. 2004,2005,2006,2014,2015,2016,2105,3005,1005,...). As it is there is definitely not enough data to work with. – Generic Human Jun 23 '12 at 14:48 ## closed as off topic by Will Jagy, sdcvvc, t.b., John Wordsworth, WilliamAug 29 '12 at 21:57 Questions on Mathematics Stack Exchange are expected to relate to math within the scope defined in the FAQ. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about closed questions here. ## 2 Answers Your code is a correct, if somewhat cumbersome, implementation of the Luhn check digit algorithm. However, as described by Nick Adams' answer to your cross-post of this question on Stack Overflow, the check digits used by BPay are not calculated using Luhn's method. Instead, what they appear to be using is a weighted sum modulo 10, with the weight of each digit given by its position in the number, starting at 1 for the leftmost digit and counting up. That is, if the digits of the original number are$a_1 a_2 \dots a_n$, the check digit will be $$c = (1 \cdot a_1 + 2 \cdot a_2 + \dotsb + n \cdot a_n) \bmod 10.$$ Here's one way to calculate this check digit in PHP code (which should give the same results as Nick Adams' code): function BPayCheckDigit ($number) {
$n = strlen($number);
$sum = 0; for ($i = 0; $i <$n; $i++) {$sum += ($i + 1) *$number{$i}; } return$sum % 10;
}

By the way, this check digit formula has a number of weaknesses compared to Luhn's method:

• Since the weights are counted from the left, the presence or absence of leading zeros affects the checksum. Thus, you need to make sure that your numbers are actually stored and manipulated as strings, or pad them to the correct length before the checksum calculation.

• Unlike in the Luhn method, verifying the checksum requires treating the check digit separately from the other digits, rather than just including it in the calculation and checking that the result comes out zero. (That is, unless the length of the numbers just happens to be nine digits including the check digit, in which case the ninth digit is assigned the weight $9 \equiv -1 \bmod 10$ and the match does work out right.)

• For even-numbered digits, this checksum cannot detect the addition or subtraction of 5 from the digit. For digits whose weight is a multiple of 5, the checksum cannot detect the addition or subtraction of any even number. In particular, digits whose weight is a multiple of 10 are not checked at all (although I believe the checksum is not intended for numbers that long anyway)!

-

For me the obvious oddity here is in the two range declarations. It looks like you want to produce one array of odd and and one array of even digits to intersect against. So you will want [1,3,5,7,9] and [0,2,4,6,8]. Instead you are producing only [1,3] and [0,2,4] for the range is limited by 4=count(\$chars) both times.

So I suspect what you want is

range(1, 9, 2)

and

range(0, 8, 2)

respectively.

EDIT: I did not run the code but in my head and even there couldn't come up with your final digits. As was said in the comments, you may need to clarify what you want to do so people can help you

-