Re:ゼロから始めるC#

C#を突然仕事で使うことになった人

JavaばっかやってましたがC#を使うことになったので備忘録的に…なんて日もあった

C#でモジュラス10 ウェイト2・1分割のチェックデジットを求める

はいどうも。
久しぶりの投稿になります。
なんやかんや社会人やってるとこういのやるの面倒になってというか仕事に追われてよ、備忘録とかで書くのもだるくなっちゃうんすね。
よく書いてる人まじですごい。そしてすごく助かる。もっとみんな書いてほしい。俺はそれをコピペしたい。

ということで、たまには僕からもコピペで解決できるコードをってね!思って投稿しようとしてるわけなんですけど、まじで何も考えずただただ上から処理してっただけなので、何ならこれ綺麗にしてほしくて投稿します。
人間打算なしには動けないもんですね。
今回はモジュラス10 ウェイト2・1分割のチェックデジットを求めるコードになります。
調べたらそのままコピペできるのなかったのでと思ってね。へへっ。
ではさっそくやっていきましょう!

チェックデジットとは

チェックデジットってなんやねん!ってことはなかったんですけど一応
符号の入力誤りなどを検出するために、元の符号に付加される数字のこと。CD、C/Dと略される。
こういう書き方されるとバカなのでわかんなくなっちゃうんですけど、要するにその数値本当にあってんの?って疑問を解消してくれる便利な値ってことです。
マイナンバーカードとかでも使われてたと思うんですけど、そういう大事な数字を入力するシーンて結構あるじゃないですか。
で、もちろん人間の皆様にはなかなか貴重な体験だと思うんですけど、犬猫畜生そして私なんてのは数字の入力とかもおぼつかないんですよ。
そういったときに、入力値の整合性をチェックしてくれる値となっております。
簡単にいうと
1111のチェックデジットが2だとするじゃないですか。んで5桁のナンバーを入力したときに
11111
とか入力すると1111のチェックデジットは2だから5桁目が1なのは不正な値だ!ってわかるってことです。

種類

人間はおりこうさんなのでこのチェックデジットってのは求める方式がいくつかあるんですけど代表的なものを紹介しますね

  • モジュラス10 ウェイト2・1分割(Luhn formula)
  • モジュラス10 ウェイト2・1一括
  • モジュラス10 ウェイト3・1.
  • モジュラス11 ウェイト2~7.
  • モジュラス11 ウェイト1~0.

わかる。わかるよ。
なんやねんこの呪文…
アタイもそう思ってた…
プレステ5なんとかエディション的な感じかなって思ってた。
でもここでは説明しません。
調べるといっぱい乗ってるので。
なんといっても早くコードを整形してほしいので!

M10W21

今回は上記の種類のうちのモジュラス10 ウェイト2・1分割というものについてやっていこうと思いますね。
M10W21って書くらしいです。最初仕様書に書いてあってモンハンワールドアイスボーン的なねってよくわかんないこと考えてました。

調べてみると
数値の各桁に、下の桁から2・1・2・1・…の順番に係数(ウェイト)を掛けます。
各桁の結果が2桁の場合には、十の位と一の位を分けて足し合わせます(分割)。
それぞれの合計を求めます。
合計を10で割り、余りを求めます(モジュラス)。
この余りを 10 から引いたもの(10 - 余り)がチェックデジットです。ただし余りが0の場合はチェックデジットも「0」になります。

ということらしいです。
わかりました?僕は赤ちゃんなので全然わかりませんでした。赤ちゃんだから仕方ないね。
はい、そういう人のためにね、ちゃんとまとめてくれてるありがたい人がいるから。
これ読んで。
[メモ] 各種チェックデジットの計算方法 - Qiita
もうすごい、めっちゃわかりやすい。
絵本しか呼んだことない僕ちゃんでも直感的にわかります。
大変助かりました。

ということで、ここに書いてあることを上から順にまんまコードにしました。

コード

もうはよ貼れや…整形してやっから…という皆さん、お待たせいたしました。
そしてよろしくお願いします。

/// <summary>
/// チェックデジット計算(モジュラス10 ウェイト2・1分割)
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
private string calcCheckDigit(string code)
{
    string ret = "";

    List<string> oddList = new List<string>();
    List<string> evenList = new List<string>();
    // reverse
    code = string.Join("", code.Reverse());
    bool oddFlg = false;

    for(int i = 0; i < code.Length; i++)
    {
        if (oddFlg)
        {
            oddList.Add(code.Substring(i, 1));
        }
        else
        {
            evenList.Add(code.Substring(i, 1));
        }

        oddFlg = !oddFlg;
    }

    // 奇数処理
    int kisu = 0;
    foreach (string s in oddList)
    {
        kisu = kisu + int.Parse(s);
    }

    // 偶数処理
    int gusu = 0;
    foreach(string s in evenList)
    {
        int num = int.Parse(s);
        num = num * 2;
        string str = num.ToString();
        if (str.Length == 1)
        {
            gusu = gusu + num;
        }
        else
        {
            for(int i = 0; i< str.Length; i++)
            {
                string str2 = str.Substring(i, 1);
                gusu = gusu + int.Parse(str2);
            }
        }
    }

    int mod = 10 - ((kisu + gusu) % 10);
    if(mod == 10)
    {
        mod = 0;
    }

    ret = mod.ToString();

    return ret;
}

はい、このメソッドにチェックデジットを求めたい値(string)を渡せば計算してチェックデジットの値(string)を返してくれます。

見て分かる通り処理を上から順になぞっただけなので無駄しかないです。
整形してくれる方大募集です。
機能性とかどうでもいいよ!っていう僕みたいな人はコピペして使ってください。

それではよろしくお願いしました。