Options

Luhn or Luhn formula - also known as modulus 1 or mod 1.

Aravindh_NavisionAravindh_Navision Member Posts: 258
Hi Friends,

Does anyone worked in Luhn algorithm or Luhn formula, also known as the "modulus 10" or "mod 10" algorithm (in Navision)?

Luhn algorithm is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers, barcodes etc., Also see this link: http://en.wikipedia.org/wiki/Modulus_10

Am totally blank about this. Can anyone please provide me with how to handle this in Navision or with links which addresses this topic?

Thanks,
Aravindh

Comments

  • Options
    geronimogeronimo Member Posts: 90
    below i've put some sample code on a way to do this checksum. I've put this in a function with a text parameter(Ptxt_String) and a boolean return value.
    Ltxt_resultstring is also a text, all the other variables are integers.
    clear(LInt_total);
    clear(LInt_TempInt);
    FOR i := 1 TO STRLEN(PTxt_String) - 1 DO BEGIN
      EVALUATE(LInt_TempInt,COPYSTR(PTxt_String,i,1));
      IF (i MOD 2) <> 0 THEN BEGIN
        Ltxt_ResultString := Ltxt_ResultString + FORMAT(LInt_TempInt);
      END ELSE BEGIN
        LInt_TempInt *= 2;
        Ltxt_ResultString := Ltxt_ResultString + FORMAT(LInt_TempInt);
      END;
    END;
    EVALUATE(LInt_TempInt,COPYSTR(PTxt_String,STRLEN(PTxt_String),1));
    Ltxt_ResultString := Ltxt_ResultString + FORMAT(LInt_TempInt);
    
    FOR i := 1 TO STRLEN(Ltxt_ResultString) DO BEGIN
      EVALUATE(LInt_TempInt,COPYSTR(Ltxt_ResultString,i,1));
      LInt_total += LInt_TempInt;
    END;
    
    EXIT((LInt_total MOD 10) = 0);
    
  • Options
    MBergerMBerger Member Posts: 413
    geronimo wrote:
    below i've put some sample code on a way to do this checksum. I've put this in a function with a text parameter(Ptxt_String) and a boolean return value.
    Ltxt_resultstring is also a text, all the other variables are integers.
    clear(LInt_total);
    clear(LInt_TempInt);
    FOR i := 1 TO STRLEN(PTxt_String) - 1 DO BEGIN
      EVALUATE(LInt_TempInt,COPYSTR(PTxt_String,i,1));
      IF (i MOD 2) <> 0 THEN BEGIN
        Ltxt_ResultString := Ltxt_ResultString + FORMAT(LInt_TempInt);
      END ELSE BEGIN
        LInt_TempInt *= 2;
        Ltxt_ResultString := Ltxt_ResultString + FORMAT(LInt_TempInt);
      END;
    END;
    EVALUATE(LInt_TempInt,COPYSTR(PTxt_String,STRLEN(PTxt_String),1));
    Ltxt_ResultString := Ltxt_ResultString + FORMAT(LInt_TempInt);
    
    FOR i := 1 TO STRLEN(Ltxt_ResultString) DO BEGIN
      EVALUATE(LInt_TempInt,COPYSTR(Ltxt_ResultString,i,1));
      LInt_total += LInt_TempInt;
    END;
    
    EXIT((LInt_total MOD 10) = 0);
    
    Ever looked up the strCheckSum() function in the helpfile ?
  • Options
    geronimogeronimo Member Posts: 90
    thanks for the hint MBerger, another new thing learned :)
  • Options
    vaprogvaprog Member Posts: 1,118
    STRCHECKSUM won't work, because it sums up the weighted digits, not the cross sum thereof.

    The following example is from Wikipedia
    Assume an example of an account number "4992739871" that will have a check digit added, making it of the form 4992739871x:
    Account number           4  9  9  2  7  3  9  8  7  1  x 
    Double every other       4 18  9  4  7  6  9 16  7  2  x 
    Sum together all numbers 64 + x
    
    To make the sum divisible by 10, we set the check digit (x) to 6, making the full account number 49927398716.
    The account number 49927398716 can be validated as follows:
    1. Double every second digit, from the rightmost: (1×2) = 2, (8×2) = 16, (3×2) = 6, (2×2) = 4, (9×2) = 18
    2. Sum all the individual digits (digits in parentheses are the products from Step 1): 6 + (2) + 7 + (1+6) + 9 + (6) + 7 + (4) + 9 + (1+8) + 4 = 70
    3. Take the sum modulo 10: 70 mod 10 = 0; the account number is probably valid.
    The sum calculated by STRCHECKSUM was 82 and therefore the check digit 8. This is because STCHECKSUM includes 18 and 16 in its sum. The Lunh algorithm, however sums up their cross sum, so adds up 1+8=9 and 1+6=7 instead.

    geronimo's Code assumes an odd number of digits in it's Ptxt_String parameter to work correctly.
  • Options
    geronimogeronimo Member Posts: 90
    vaprog wrote:
    geronimo's Code assumes an odd number of digits in it's Ptxt_String parameter to work correctly.
    how do you mean?
  • Options
    vaprogvaprog Member Posts: 1,118
    This is the description of the algorithm from Wikipedia as above:
    1. Counting from the check digit, which is the rightmost, and moving left, double the value of every second digit.
    2. Sum the digits of the products (eg, 10 = 1 + 0 = 1, 14 = 1 + 4 = 5) together with the undoubled digits from the original number.
    3. If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the Luhn formula; else it is not valid.
    Item 1 says, you need to start from the right, and double every second digit.
    geronimo's code starts from the left.
    Therefore it matters whether you have an even or odd number of digits to evaluate.
    The code may easily be anhanced, though.
  • Options
    geronimogeronimo Member Posts: 90
    vaprog wrote:
    This is the description of the algorithm from Wikipedia as above:
    1. Counting from the check digit, which is the rightmost, and moving left, double the value of every second digit.
    2. Sum the digits of the products (eg, 10 = 1 + 0 = 1, 14 = 1 + 4 = 5) together with the undoubled digits from the original number.
    3. If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the Luhn formula; else it is not valid.
    Item 1 says, you need to start from the right, and double every second digit.
    geronimo's code starts from the left.
    Therefore it matters whether you have an even or odd number of digits to evaluate.
    The code may easily be anhanced, though.


    ah i must have read past that part it is indeed fairly easy to adapt the code however :)
  • Options
    Aravindh_NavisionAravindh_Navision Member Posts: 258
    Hai all,

    Thank you guys for joining in this discussion and providing solutions and your ideas. It was useful. The client had changed the logic now which is given below.

    I need to find the verification digit to the following value: 3070841326319000361243033388633240620117 (Length - 39 char)

    1. Sum odd positions [3, 7, 8, 1, 2, 3, 9, 0, 3, 1, 4, 0, 3, 8, 6, 3, 4, 6, 0, 1]. (SumOdd = 72)
    2. Multiply SumOdd * 3. (Mult = 72 * 3 = 216)
    3. Sum even positions [0, 0, 4, 3, 6, 1, 0, 0, 6, 2, 3, 3, 3, 8, 3, 2, 0, 2, 1]. (SumEven = 47)
    4. Sum = Mult + SumEven, (Sum = 216 + 47 = 263)
    5. Verification digit 7. (We need to add the integer value 7 to 263 so the nearest higher value which should divisible by 10 and the remainder remains 0.)

    To find the lowest number (verification digit)...:
    VeriDigit = 10 - (Sum - (int(Sum/10) * 10))
    VeriDigit = 10 - (263 -(int(263/10) * 10))
    = 10 - (263 - (26 * 10))
    = 10 - (263 - 260) = 10 - 3
    VeriDigit = 7

    Can anyone please help me in solving this?

    Thanks in advance,

    Aravindh
  • Options
    Ephraim_07Ephraim_07 Member Posts: 9
    Hi Friends,

    Does anyone worked in Luhn algorithm or Luhn formula, also known as the "modulus 10" or "mod 10" algorithm (in Navision)?

    Luhn algorithm is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers, barcodes etc., Also see this link: http://en.wikipedia.org/wiki/Modulus_10

    Am totally blank about this. Can anyone please provide me with how to handle this in Navision or with links which addresses this topic?

    Thanks,
    Aravindh

    Please find my solution for NAV C/AL in the following post >> https://forum.mibuso.com/discussion/77912/luhn-algorithm-modulus-10-in-dynamics-nav-c-al-code-creating-a-check-digit/p1?new=1

    This can easily be converted to work in Business Central AL code
  • Options
    Ephraim_07Ephraim_07 Member Posts: 9
    edited 2024-02-14
    Hai all,

    Thank you guys for joining in this discussion and providing solutions and your ideas. It was useful. The client had changed the logic now which is given below.

    I need to find the verification digit to the following value: 3070841326319000361243033388633240620117 (Length - 39 char)

    1. Sum odd positions [3, 7, 8, 1, 2, 3, 9, 0, 3, 1, 4, 0, 3, 8, 6, 3, 4, 6, 0, 1]. (SumOdd = 72)
    2. Multiply SumOdd * 3. (Mult = 72 * 3 = 216)
    3. Sum even positions [0, 0, 4, 3, 6, 1, 0, 0, 6, 2, 3, 3, 3, 8, 3, 2, 0, 2, 1]. (SumEven = 47)
    4. Sum = Mult + SumEven, (Sum = 216 + 47 = 263)
    5. Verification digit 7. (We need to add the integer value 7 to 263 so the nearest higher value which should divisible by 10 and the remainder remains 0.)

    To find the lowest number (verification digit)...:
    VeriDigit = 10 - (Sum - (int(Sum/10) * 10))
    VeriDigit = 10 - (263 -(int(263/10) * 10))
    = 10 - (263 - (26 * 10))
    = 10 - (263 - 260) = 10 - 3
    VeriDigit = 7

    Can anyone please help me in solving this?

    Thanks in advance,

    Aravindh

    Hello Aravindh,

    Here is my take on a solution for your problem. It is similar to the solution I posted earlier.
    I was initially confused by the results but I realized I had to take the last digit out of the number before putting it into the algorithm :#

    But I must ask why the sum of odd numbers is multiplied by 3 specifically and is it always 3?

    Anyways, here is the code below:

    Variables:
    Name DataType Subtype Length
    i Integer
    LengthOfDigit Integer
    CodeCharacter Code 250
    Product BigInteger
    SumProduct BigInteger
    SingleDigit Integer
    SumOfOddNumbers Integer
    SumOfEvenNumbers Integer
    
    OrigCode := '307084132631900036124303338863324062011';
    
    LengthOfDigit := STRLEN(OrigCode);
    CLEAR(SumOfOddNumbers);  CLEAR(Product); CLEAR(SumProduct);
    
    FOR i := 1 TO LengthOfDigit DO BEGIN
      CodeCharacter[i] := COPYSTR(OrigCode,i,1);      // Get the individual digit in that position
    
      //Check of the position of the digit is an odd number. All odd numbers will be (i MOD 2 = 1) or more
      // If Odd, the multiply by 2, else multiply by 1
      //-------------------------------------------------------------
      IF i MOD 2 <> 0 THEN BEGIN                        //Odd numbers                          
        EVALUATE(SingleDigit[i],CodeCharacter[i]);   //Convert code to an integer for computation                                 
        SumOfOddNumbers :=  SumOfOddNumbers + SingleDigit[i];
      END ELSE BEGIN
        EVALUATE(SingleDigit[i],CodeCharacter[i]);    //Even Numbers
        SumOfEvenNumbers :=  SumOfEvenNumbers + SingleDigit[i];
      END;
    
    END;
    
    Product := SumOfOddNumbers * 3;
    
    SumProduct := Product + SumOfEvenNumbers;
    
    //We can use the MOD function to get the number you mentioned in your comment. This is much faster than the formula of "VeriDigit = 10 - (Sum - (int(Sum/10) * 10))" 
    IF SumProduct MOD 10 <> 0 THEN   
        VerificationDigit := 10 - (SumProduct MOD 10)
      ELSE
        VerificationDigit := 0;
    	
    
Sign In or Register to comment.