Tuesday, March 15, 2011

Mod Check 11 CPU too high

I put together a VB.NET function to create a mod 11 check digit. The code is in no way unique to any individual or scenario. Anyone can find hundreds of variations in any basic example book, bulletin board or web site.
The function is inefficient; it uses too much CPU for too long to be useful in the “real world”.
What is done wrong or in a way that can be improved and still function on a 32-bit OS such as Windows XP Sp3, Vista and/or 7?

    ''' <summary>
    ''' Mod Check 11 pegging CPU too high
    ''' </summary>
    ''' <param name="controlNumber">base Account Number i.e. 000345</param>
    ''' <param name="divisor">11</param>
    ''' <param name="weights">137</param>
    ''' <returns>account number i.e. 0003456</returns>
    ''' <remarks>The basics are standard create and attach a check digit to an "base Account"</remarks>
    Public Shared Function CalculateMOD(ByVal controlNumber As String, ByVal divisor As Int32, ByVal weights As Int64) As String
        ' Get Weights Char Array
        Dim validWeights() As Char = weights.ToString.ToCharArray()
        Dim formulaValidWeights As String = New String(validWeights)
        Dim sum As Int32 = 0
        Dim checkDigit As String = String.Empty
        ''Set the weight beginning=2.  
        Dim weightindex As Int32 = 0
        Dim baseAccount() As Char = controlNumber.ToCharArray()
        ' Reverse baseAccount Char Array order
        Array.Reverse(baseAccount)
        ' controlNumberArray - baseAccount Char Array reversed
        Dim controlNumberArray As String = New String(baseAccount)
        For controlNumberIndex As Int32 = 0 To controlNumberArray.Length - 1
            ''sets the weight count to loop from 0 up to weight length.  
            If (weightindex > validWeights.Length - 1) Then
                ''resets weightcount to 0 again.  
                weightindex = 0
            End If
            sum += Convert.ToInt32(controlNumberArray.Substring(controlNumberIndex, 1), CultureInfo.InvariantCulture) * Convert.ToInt32(formulaValidWeights.Substring(weightindex, 1))
            weightindex += 1
        Next
        Dim remainder As Int32 = sum Mod divisor
        Select Case remainder
            Case 0
                checkDigit = Convert.ToString(0, CultureInfo.InvariantCulture)
            Case 1
                checkDigit = "-"
            Case Else
                checkDigit = Convert.ToString((divisor - remainder), CultureInfo.InvariantCulture)
        End Select
        controlNumber = controlNumber + checkDigit
        Return controlNumber
    End Function