[Tex/LaTex] Calculating checksum

calculations

I would like to calculate a checksum in LaTeX. My problem is that I don't know how to get the numeric value of a char.

Here is the pseudo code of the algorithm:

var input = "123456789";
car output = "";
var checksum = 0;
var weight = 10;

foreach(Char c in input) {
    checksum += Char.GetNumericValue(c) * weight;
    weight--;
}

checksum = 11-(checksum mod 11);
if(checksum == 10)
    output += "X";
else if (checksum == 11)
    output += "0";
else
    output += checksum;

print output;

Actually I tried this using the packages forloop and xstring:

\newcommand{\inputstr}{123456789}
\newcounter{i}
\newcounter{c}
\forloop{i}{1}{\value{i} < 10}{%
    %\StrChar{\inputstr}{\value{i}} % returns one char
    \setcounter{c}{\value{\StrChar{\inputstr}{\value{i}}}} % here is no convertion :(
}

Multiply and addition should be also no problem with \multiply and \addcounter but how to do the modulo operation?

Best Answer

If you have an argument as an character, i.e. #1=A, then `#1 will give you the ASCII number of this character. If you want that the character '0' gives you a numeric value of 0, and so on, you simply have to subtract the value `0 from each value. Luckily then characters for the digits are coded in numeric order in ASCII, i.e. `0-`1 = 1 etc.

I would loop over the input text yourself by putting it in front of an end-marker and reading one character a time in a recursive fashion.

\documentclass{article}
\usepackage{calc}

\newcounter{checksum}
\newcounter{weight}
\makeatletter
\newcommand\checksum[1]{%
    \setcounter{checksum}{0}%
    \setcounter{weight}{10}%
    \expandafter\@checksum#1\@nnil
    \loop\ifnum\value{checksum}>10
        \addtocounter{checksum}{-11}%
    \repeat
    \setcounter{checksum}{11-\value{checksum}}%
    \ifnum\value{checksum}=10
        \def\checksumdigit{X}%
    \else
    \ifnum\value{checksum}=11
        \def\checksumdigit{0}%
    \else
        \edef\checksumdigit{\arabic{checksum}}%
    \fi\fi
    \checksumdigit
}
% Reads the input one token a time, should only contains normal characters!
\def\@checksum#1{%
    \ifx\@nnil#1\relax\else % stop looping when endmarker is read
        \addtocounter{checksum}{\value{weight}*(`#1-`0)}%
        \addtocounter{weight}{-1}%
        \expandafter\@checksum % Recursive call => loop
    \fi
}
\makeatother




\begin{document}

\checksum{383480757}%5

\checksum{055215295}%1

\checksum{020113448}%9

\end{document}

This stores the checksum digit into \checksumdigit and prints it in the text. I tested it successfully on the three books above.