0

mod10アルゴリズムのLINQ実装を作成しました。

ソースコード:

string number = "7992739871";
int mod10sum = number.Reverse()
    .Select((c, i) => (c - '0') << ((i + 1) & 1)) // Double every other digit and sum the digits of the products (e.g., 10: 1 + 0 = 1, 14: 1 + 4 = 5) 
    .Sum(c => c - '0') % 10;                      // together with the undoubled digits from the original number

string checkDigit = (mod10sum == 0 ? 0 : 10 - mod10sum).ToString("0");
Console.WriteLine(checkDigit);

のように、7992739871数値にはチェックディジットが3;として含まれている必要があります。しかし、私が得ているのは15です。

私が間違っていることは何ですか?間違いは非常に小さいと思いますが、見つけることができません。

4

2 に答える 2

7

問題はSelectメソッドにあります。(アルゴリズムで説明されているように)すべての数字を合計するには、 (例のように)10代わりに101を返す必要があります。414

これを行う最も簡単なただし、最適である必要はありませんSelect)方法は、から( 14- string> "14")までの数値を確認し、。を使用して文字列文字を分割することSelectManyです。

したがって、コードは次のようになります。

int mod10sum = number.Reverse()
    .SelectMany((c, i) => ((c - '0') << ((i + 1) & 1)).ToString())
    .Sum(c => c - '0') % 10;

checkDigit = (mod10sum == 0 ? 0 : 10 - mod10sum).ToString("0");
Console.WriteLine(checkDigit);

少し理論

LINQSelectManyは返しますIEnumerable<>string(IEnumerable)を返すと、 SelectMany「splits」が文字列を文字に返したのはそのためです。

Microsoftには、さまざまなLINQサンプルを含む非常に優れたページ(101 LINQサンプル)があります。

編集

intまた、からへの変換に取り組むことをお勧めしstringます。私は昨日文字通り同様のプロジェクトに取り組んでいましたが、私の場合、そのメソッドを何百万回も呼び出すため、パフォーマンスの観点から変換は少し問題があります。たくさんのmod10を計算する必要がある場合は、それが最善の解決策ではない可能性があります。

于 2013-01-09T12:50:55.053 に答える
2

を変更しSumます。

この時点では、文字のシーケンスはありませんが、元の各数字の適切な値として1つまたは2つあります。

したがって、減算する必要はありません。0これらの整数のそれぞれの桁の合計を計算する必要があります。(小さいことがわかっているので)これは次のように簡単に実行できます。

.Sum(i => (i % 10) + (i / 10))

与える

string number = "7992739871";
int mod10sum = number.Reverse()
    .Select((c, i) => (c - '0') << ((i + 1) & 1)) 
    .Sum(i => (i % 10) + (i / 10)) % 10;

ToString()これは、結果を呼び出して反復するよりも効率的です。

于 2013-01-09T13:00:43.983 に答える