MOD10

Bakgrunn

Kontrollsifferet skal avdekke om det er gjort inntastingsfeil eller feil ved OCR-lesing. Denne algoritmen er best på å avdekke gale enkeltsifre, da ett enkelt siffer feil alltid vil gi et annet kontrollsiffer. Dersom flere sifre er feil, vil sjansene øke for at kontrollsifferet regnes ut til det samme og at feilen ikke oppdages. Om en tilfeldig tallrekke kontrolleres, er sjansen 10 % for at siste siffer stemmer med kontrollsiffer-algoritmen.
Denne algoritmen er også designet til å avdekke en ting til: Dersom to siffer har byttet plass, vil kontrollsifferet bli et annet. Derfor brukes vekttallene 21212121.. og så videre Denne typen feil er det noe økt sjanse for ved inntasting av lange KID-nummer.
Når det gjelder KID-nummer, kontrolleres også antall siffer det skal være, slik at et ekstra siffer eller et siffer for lite også gir feil KID.
Dersom et feil KID-nummer skulle slippe gjennom, er det to muligheter for mottakeren: Enten er KID-nummeret et annet gyldig nummer som er utstedt på en annen faktura, slik at betalingen knyttes til feil kunde, noe som kan være vanskelig å oppdage, og kan resultere i feil tilbakebetalinger. Den andre muligheten er at KID-nummeret ikke er tatt i bruk eller er en ugyldig KID. Dette vil mottakeren kunne avdekke, og vil kunne kontrollere nærmere hvem som har betalt manuelt. Jo kortere KID-nummer som benyttes (relativt til antall gyldige fakturaer), jo mer sannsynlig er det at feil som slipper gjennom resulterer i et annet benyttet nummer.
Lange KID-nummer som inneholder både kundenummer og fakturanummer regnes som meget sikre, siden feil i den ene eller den andre delen nesten alltid vil kunne oppdages. At feil i begge delene tilfeldigvis matcher en annens kundenummer/fakturanummer-kombinasjon er svært usannsynlig.

PHP

$kid_u = "180986";$kontrollsiffer = mod10($kid_u);echo $kid_u . $kontrollsiffer;function mod10($kid_u) {
$siffer = str_split(strrev($kid_u));
$sum = 0;
for($i = 0; $i < count($siffer); ++$i) 
$sum += ( $i & 1 ) ? $siffer[$i] : tverrsum($siffer[$i] * 2);

$sum = (($sum == 0) ? 0 : 10 - substr($sum, -1));
if($sum == 10)
$sum=0;
return $sum;}function tverrsum($tall) {
return array_sum(str_split($tall));}

Python

kid_mod10 = lambda a: "%s%s" % (a, (10-(sum([int(n) for n in list("".join([str(int(val)*[2,1][idx%2]) for idx,val in enumerate(list(str(a))[::-1])]))])%10))%10)

Haskell

kid10 :: [Int] -> [Int]kid10 nr = nr ++ [ctrl $ sum (map tv2 multi)]
    where tv2 t = t `div` 10 + t `mod` 10
        multi = zipWith (*) (reverse nr) (cycle [2,1])
        ctrl k = (10 - (k `mod` 10)) `mod` 10

C#

//USAGE: Mod10("502114008060") --> 8. The controlnumber is 8. public static int Mod10(string kid)
        {
            bool isOne = false;
            int controlNumber = 0;
            foreach (char number in kid.Reverse())
            {
                var intNumber = Int32.Parse(number.ToString());
                var sum = isOne ? intNumber : 2 * intNumber;
                if (sum > 9)
                {
                    sum = (sum%10) + 1;
                }
                isOne = !isOne;
                controlNumber += sum;
            }
            return (10 - (controlNumber % 10)) % 10 == 0 ? 0 : 10 - (controlNumber % 10) ;
        }

Kotlin

fun checksumMOD10(number: String): Boolean {
return number.toBigIntegerOrNull()?.let {
val lastDigit = Character.getNumericValue(number[number.length - 1])
var sum = 0
var alternate = false
for (i in number.length - 2 downTo 0) {
var n = Character.getNumericValue(number[i])
if (alternate) {
n *= 2
if (n > 9) {
n = n % 10 + 1
}
}
sum += n
alternate = !alternate
}
val remainder = sum % 10
return when (remainder) {
0 -> lastDigit == 0
else -> lastDigit == 10 - remainder
}
} ?: false}

Matlab

function checkNum = mod10CheckSum(num) if length(num) == 1
numVec = fliplr(num2vec(num)); 
else
numVec = fliplr(num); 
end

mult = 2.*ones(1,length(numVec)); 
mult(2:2:length(numVec)) = mult(2:2:length(numVec)) ./ 2; 
sumOfProd = sum( numVec .* mult ); 
checkNum = mod( 10 - mod( sumOfProd,10 ) , 10 ); 

end % mod10CheckSum%-------------------------------------------------------function vec = num2vec(num)% Hvis du ikke har laget en slik funksjon fra før av. Gjør om tall til vektormaxPow = length(num2str(num));vec = zeros(1,maxPow);pow = maxPow - 1;for i = 1:maxPow
    vec(i) = floor( num/(10^pow) );
    num = num - vec(i)*10^pow;
    pow = pow - 1;endend % num2vec

Javascript

1 /* luhn 10 aka MOD10 2  * @v     : input number as string 3  * @check : [true | false] Whether or not to get or check 4  *          the given number.                         Default false 5  * @debug : [true | false] Print debug information.   Default false 6  * 7  * Return boolean if check, else check digit. 8  * ****************************************************************/ 9 function luhn10 (v, check, debug) {10     let r, i,11         a = v.replace(/[^\d]/g, '').split(''),12         s = 0,13         m = check ? 1 : 014     ;15     for (i = a.length - 1; i >= 0; --i) {16         if ((m ^= 1))17             if ((a[i] *= 2) > 9)18                 a[i] -= 9;19         s += +a[i];20     }21     if ((r = (10 - (s % 10)) % 10) === 10)22         r = 0;23     if (debug) {24         console.log(25             `${v} => ${s} % 10 -> ${r} `,26             `${check ? (r === 0 ? 'OK' : 'BAD') : ''}`27         );28     }29     return check ? r === 0 : r;30 }31 32 // Example:33 // get check digit34 result = luhn10 ('62512482'); 
35 // check value36 result = luhn10 ('625124821', true);