我创建了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);
Run Code Online (Sandbox Code Playgroud)
根据示例,7992739871数字应该具有校验位3; 但是,我得到的是15.
我做错了什么?我确信错误很小但找不到.
问题在于Select方法.为了总结所有的数字(如算法描述),你就需要返回1和0替代10,1以及4替代14(如你的例子).
在最简单的(但不一定是最优化的)的方式来做到这一点是从conert号Select到string(14 - >"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);
Run Code Online (Sandbox Code Playgroud)
一点理论
LINQ SelectMany返回IEnumerable<>.当你返回string(这是IEnumerable)时,这就是为什么SelectMany"将"拆分"返回字符串".
微软有非常好的页面(101 LINQ样本)和不同的LINQ样本,可以帮助你.
编辑
我还建议对从转换工作int来string.昨天我正在从事类似的项目,在我的情况下,从性能的角度来看转换有点问题,因为我们称这种方法为数百万次.如果你必须计算很多mod10,那么它可能不是最好的解决方案.