我目前正在开发VS2010中的Windows窗体,它应该为新的部件号创建UPC-A并将它们存储在数据库中。到目前为止,我仍然试图把各个部分拼凑起来,我在计算校验位方面遇到了问题。我提出了以下两种情况:
场景1:按照我们目前在Excel中的方式进行计算:
string value = uPCDataSet.UPC.Rows[uPCDataSet.UPC.Rows.Count - 1]["UPCNumber"].ToString();
string manCode = value.Substring(1, 5);
string prodCode = value.Substring(7, 5);
int first = Math.Abs(Convert.ToInt32(value));
while (first >= 10)
first /= 10;
int chkDigitSubtotal;
string UPCNumber = first + manCode + prodCode;
chkDigitSubtotal = Convert.ToInt32((UPCNumber.Substring(1, 1)) + (UPCNumber.Substring(3, 1)) +
(UPCNumber.Substring(5, 1)) + (UPCNumber.Substring(7, 1)) + (UPCNumber.Substring(9, 1)) +
(UPCNumber.Substring(11, 1)));
chkDigitSubtotal = (3 * chkDigitSubtotal) + Convert.ToInt32((UPCNumber.Substring(2, 1)) +
(UPCNumber.Substring(4, 1)) + (UPCNumber.Substring(6, 1)) + (UPCNumber.Substring(8, 1)) +
(UPCNumber.Substring(10, 1)));
string chkDigit = ((300 - chkDigitSubtotal).ToString()).Substring(12, 1);
当我运行此代码时,我收到错误“对于Int32,值太大或太小”。我不明白为什么“值”是一个有{12}个字符的varchar
(它们都是数字)。
场景2:我发现了一个在线剪切的代码。这段代码有效,但给了我错误的校验位。我正在使用我们使用Excel工作表计算的UPC:
string value = "606891001678"; //valid UPC with check digit
string UPCBody = value.Substring(0, 11);
int sum = 0;
bool odd = true;
for (int i = value.Length - 1; i >= 0; i--)
{
if (odd == true)
{
int tSum = Convert.ToInt32(value[i].ToString()) * 2;
if (tSum >= 10)
{
string tData = tSum.ToString();
tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
}
sum += tSum;
}
else
sum += Convert.ToInt32(value[i].ToString());
odd = !odd;
}
int result = (((sum / 10)+1) *10) - sum;
result = result % 10;
MessageBox.Show(UPCBody + " & " + result);
在这个例子中,校验位显然应该是8,但它返回2。 我花了很多时间在这上面并且可以使用一些建议。为什么我在第一个场景中出现错误,为什么我在第二个场景中得到的不同校验位应该是什么?
提前感谢您的帮助!
克里斯
编辑:
我删除了之前的两个编辑,因为代码存在缺陷,因为我没有得到正确的结果。我发现我们使用杜鹃花条形码,他们有自己的计算校验位的方法(参见ChkDigitSubtotal)。 所以下面的代码工作,并为我的方案提供了正确的校验位。我认为这个代码将适用于所有UPC-A计算的chkDigitSubtotal。感谢哈里森的出色指导和足智多谋的回答!
string value = uPCDataSet.UPC.Rows[uPCDataSet.UPC.Rows.Count - 1]
["UPCNumber"].ToString();
long chkDigitOdd;
long chkDigitEven;
long chkDigitSubtotal;
string UPCNumber = value.Substring(0, 11);
chkDigitOdd = Convert.ToInt64(UPCNumber.Substring(0, 1)) +
Convert.ToInt64(UPCNumber.Substring(2, 1)) + Convert.ToInt64(UPCNumber.Substring(4, 1))
+ Convert.ToInt64(UPCNumber.Substring(6, 1)) + Convert.ToInt64(UPCNumber.Substring(8,
1)) + Convert.ToInt64(UPCNumber.Substring(10, 1));
chkDigitOdd = (3 * chkDigitOdd);
chkDigitEven = Convert.ToInt64(UPCNumber.Substring(1, 1)) +
Convert.ToInt64(UPCNumber.Substring(3, 1)) + Convert.ToInt64(UPCNumber.Substring(5, 1))
+ Convert.ToInt64(UPCNumber.Substring(7, 1)) + Convert.ToInt64(UPCNumber.Substring(9,
1));
chkDigitSubtotal = (300-(chkDigitEven + chkDigitOdd));
string chkDigit = chkDigitSubtotal.ToString();
chkDigit = chkDigit.Substring(chkDigit.Length - 1, 1);
答案 0 :(得分:1)
基于我在wikipedia上阅读的内容,您在第一个示例中错误地进行了计算。
String.Substring
+ String.Subtring
或" 1" +" 1" =" 11"。你是
寻找1 + 1 = 2。您需要先将每个子字符串转换为int
添加。二进制+运算符是为数字和字符串类型预定义的。对于 数字类型,+计算其两个操作数的总和。 当一个或 两个操作数都是string类型,+连接字符串 操作数的表示。
String.Substring
基于0,所以你错过了
{偶数位数String.Substring(0,1)
startIndex:子字符串从零开始的字符位置 在这种情况下。
string chkDigit = ((300 - chkDigitSubtotal).ToString()).Substring(12, 1);
您试图从基于第12个0的字符中取Substring
,或者从第13个字符中取1个长度。但是,chkDigitSubtotal的值不会那么大/长。
就你的错误而言,正如金龙在他的回答中所述,你将12个字符串转换为数字,这不符合Int32
并且你应该使用一个长的。
int first = Math.Abs(Convert.ToInt32(value));
转到
long first = Math.Abs(Convert.ToInt64(value));
我会检查你的计算实际上是先在前面的步骤中按逻辑运行。
<强>更新强>
在编辑2 中,您的最后一行看起来% operator
周围的变量发生了逆转。你想取109的余数除以10(即9),你的代码取10的剩余部分除以109(即0)所以改变。
chkDigitSubtotal = 10 - (10 % (chkDigitEven + chkDigitOdd));
到
chkDigitSubtotal = 10 - ((chkDigitEven + chkDigitOdd) % 10);
现在10 - 9 = 1这是你的checkDigit。
答案 1 :(得分:0)
如果value
是一个12位长的字符串,则它太大而无法放入int
。请改用long