Overview

This is a collection of implementations of the MPAN check digit algorithm in a variety of programming languages. It used to be on the Wikipedia MPAN page, but was removed by somebody because:

Wikipedia is an encyclopaedia, not a code repository or location for comparison of different languages and scripts.

I'd like to emphasize that the code here isn't my own work (apart from the Python example), it's the work of the relevant contributors to the Wikipedia page up to the time of the section being removed from the page. The individual contributors can be seen on the history page.

This work is released under CC-BY-SA.

The final digit in the MPAN is the check digit, and validates the previous 12 (the core) using a modulus 11 test. The check digit is calculated thus:

  1. Multiply the first digit by 3
  2. Multiply the second digit by the next prime number (5)
  3. Repeat this for each digit (missing 11 out on the list of prime numbers for the purposes of this algorithm.)
  4. Add up all these products.
  5. The check digit is the sum modulo 11 modulo 10.

Java

int checkDigit(String toCheck) {
    int[] primes = {3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43};
    int sum = 0;
    for (int i = 0; i < primes.length; i++) {
        sum += Character.getNumericValue(toCheck.charAt(i)) * primes[i];
}
return sum % 11 % 10;
}

Pascal / Delphi

function CheckDigit(MPANCore : array of Byte): Integer;
const
    Primes : array [0..11] of Byte = (3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43);
var
    i : integer;
begin
    Result := 0;

    for i := 0 to 11 do
        Result := Result + (MPANCore[i] * Primes[i]);

    Result := Result mod 11 mod 10;
end;

Ruby

def check_digit(mpan)
    primes = [3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43]
    (0..11).inject(0) { |sum, n| sum + (mpan[n, 1].to_i * primes[n]) } % 11 % 10
end

Visual Basic

Public Function mpancheck(mpan As String) As Boolean

On Error GoTo inval

    Dim c As Variant, sum As Integer

    c = Array(0, 3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43)

    For i = 1 To 12
        sum = sum + (Mid(mpan, i, 1) * c(i))
    Next i

    If Right(mpan, 1) = ((sum Mod 11) Mod 10) Then
        mpancheck = True
    Else
        inval:
            mpancheck = False
    End If

End Function

VisualBasic.Net 2010

Public Function mpancheck(mpan As String) As Boolean

    On Error GoTo inval

    Dim c As Object, sum As Integer

    c = New List(Of Integer) From {0, 3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43}

    For i = 1 To 12
        sum = sum + (Mid(mpan, i, 1) * c(i))
    Next i

    If sRight(mpan, 1) = ((sum Mod 11) Mod 10) Then
        Return True
    Else
inval:
        Return False
    End If

End Function
Public Function sRight(sSTRING As String, iLEN As Integer) As String
    Dim sRET As String = ""
    Try
        If iLEN >= Len(sSTRING) Then
            sRET = sSTRING
        End If
        sRET = Mid(sSTRING, Len(sSTRING) - (iLEN - 1), iLEN)
    Catch ex As Exception
        sRET = ""
    End Try
    Return sRET

End Function

VB.Net 2010, avoiding the use of VB6 Compatibility Library

Public Function MPANIsValid(mpan As String) As Boolean

        ' Set initial conditions.
        Dim validationResult As Boolean = False

        If mpan.Length > 12 Then

                'Read the check digit into an Integer variable.
                Dim intCheckDigit As Integer
                If Integer.TryParse(mpan.Substring(mpan.Length - 1), intCheckDigit) Then

                        Dim strTest As String = mpan.Substring(mpan.Length-13,12)
                        Dim intPrimes() As Integer = { 3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43}
                        Dim productTotal As Integer = 0
                        Dim blnError As Boolean = False

                        For i As Integer = 0 To 11 Step 1
                Dim intTestDigit As Integer
                If Integer.TryParse(mpan.Substring(i,1), intTestDigit) Then
                    productTotal += (intTestDigit * intPrimes(i))
                Else
                    blnError = True
                    Exit For
                End If
            Next

            If Not blnError Then
                validationResult = ((productTotal Mod 11 Mod 10) = intCheckDigit)   
            Else
                validationResult = False ' Due to a parsing error.  
            End If

        End If

    End If

    Return validationResult

End Function

C#

public static bool MPANIsValid(string mpan)
{

    // Set initial conditions.
    bool validationResult = false;

    if (mpan.Length > 12) {

        //Read the check digit into an Integer variable.
        int intCheckDigit = 0;
        if (int.TryParse(mpan.Substring(mpan.Length - 1), out intCheckDigit)) {

            string strTest = mpan.Substring(mpan.Length - 13, 12);
            int[] intPrimes = {3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43};
            int productTotal = 0;
            bool blnError = false;

            for (int i = 0; i <= 11; i++) {
                int intTestDigit = 0;
                if (int.TryParse(mpan.Substring(i, 1), out intTestDigit)) {
                    productTotal += (intTestDigit * intPrimes[i]);
                } else {
                    blnError = true;
                    break; 
                }
            }

            if (!blnError) {
                validationResult = ((productTotal % 11 % 10) == intCheckDigit);
            } else {
                validationResult = false; // Due to a parsing error.    
            }

        }

    }

    return validationResult;

}

Formula in Excel

'MPAN in Cell A1

=IF(TEXT((MOD(MOD(SUM((MID(A1,1,1)*3),(MID(A1,2,1)*5),(MID(A1,3,1)*7),(MID(A1,4,1)*13), (MID(A1,5,1)*17),(MID(A1,6,1)*19),(MID(A1,7,1)*23),(MID(A1,8,1)*29),(MID(A1,9,1)*31), (MID(A1,10,1)*37),(MID(A1,11,1)*41),(MID(A1,12,1)*43)),11),10)),0)=TEXT(TRIM(RIGHT(A1,1)), 0),"Correct","Invalid Mpan")

Python

def check_digit(mpan):
    """ 
        @mpan = The first 12 digits of the MPAN number, excluding the check digit
    """
    return sum(prime * int(digit) for prime, digit in \
            zip([3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43], mpan)) % 11 % 10

PL/SQL

create or replace function mpan_check(mpan in varchar2) return boolean is
  res integer := 0;
  TYPE prime_tab IS VARRAY(12) OF integer;
  primes prime_tab := prime_tab (3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43);
begin  
  for i in 1..12 loop    
    res := res + to_number( substr( mpan, i, 1) ) * primes (i);
  end loop;  
  return to_char(mod(mod(res , 11) , 10)) = substr(mpan,13,1);
end mpan_check;

Javascript

    function checkMPAN(mpan) {
        var primes = [3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43];
        var sum = 0;
        var m = mpan.toString();

        if ((m.length - 1) == primes.length) {
            for (var i = 0; i < primes.length; i++) {
                sum += parseInt(m.charAt(i)) * primes[i];
            }
            return (((sum % 11 % 10) == m.charAt(12)) ? true : false);

        }
        else {
            return false;
        }
    }

PHP

public function checkMPAN($mpan)
{
    $primes = array(3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43);
    $sum = 0;
    $mpan = str_split($mpan);

    if ((count($mpan) - 1) == count($primes)) {
        for ($i = 0; $i < count($primes); $i++) {
        $sum += $mpan[$i] * $primes[$i];
        }
        return (($sum % 11 % 10) == end($mpan)) ? true : false;
    } else {
        return false;
    }
}

SQL Server

CREATE FUNCTION is_valid_mpan 
(  @mpan    VARCHAR(50)  )
RETURNS INT
AS
  BEGIN
        --Tim Foster (2013-01-04)
        DECLARE @is_mpan    INT
                ,@x     INT = 1
                ,@sum       INT = 0

        DECLARE @arr    TABLE (id INT IDENTITY(1, 1), val INT)

        INSERT INTO @arr(val) VALUES(3),(5),(7),(13),(17),(19),(23),(29),(31),(37),(41),(43)

        WHILE @x <= 12
          BEGIN
                SELECT  @sum    = @sum + (SUBSTRING(@mpan, @x, 1) * val)
                FROM    @arr
                WHERE   id  = @x

                SELECT @x = @x + 1
          END

        IF RIGHT(@mpan, 1) = ((@sum % 11) % 10)
          BEGIN
                SELECT @is_mpan = 1
          END
        ELSE
          BEGIN
                SELECT @is_mpan = 0
          END

        RETURN @is_mpan
END