function isValidGtin(barcode) {
var code = "00000" + barcode;
code = code.substring(code.length - 14);
var sum = 0;
for (var i = 0; i < code.length; i++) {
sum += code[i] * ((i % 2 == 0) ? 3 : 1);
}
return (sum % 10) == 0;
}
public static char CalculateCheckSumDigit(string code)
{
// https://www.gs1.org/services/how-calculate-check-digit-manually
var reversed = code.Reverse().Skip(1);
int sum = 0;
int multiplier = 3;
foreach(char c in reversed)
{
if (multiplier == 3)
{
sum += (c - 0x30) * multiplier;
multiplier = 1;
}
else
{
sum += (c - 0x30) * multiplier;
multiplier = 3;
}
}
int closestTenth = (sum + 9) / 10 * 10;
return (char)((closestTenth - sum) + 0x30);
}
我知道这个问题是在 .net/C# 的背景下提出的。然而,我来到这个页面寻找同样问题的答案,但是在 Groovy 的背景下。
由于我实际上成功地使用了这个页面上的信息来解决自己的问题,所以我想分享一下结果。
特别是 AlexDev、Zack Peterson 和 Mitch 的答案对我很有帮助。
/*
Check digit calculation is based on modulus 10 with digits in an odd
position (from right to left) being weighted 1 and even position digits
being weighted 3.
For further information on EAN-13 see:
Wikipedia - European Article Number: http://en.wikipedia.org/wiki/International_Article_Number_%28EAN%29
Implementation based on https://dev59.com/Dmkw5IYBdhLWcg3wGGq8
Tests can be found there too
*/
boolean isValidEan(String code){
returnValue = false
if (code ==~ /\d{8}|\d{12,14}/){ //Matches if String code contains 8, 12, 13 or 14 digits
assert [8,12,13,14].contains(code.size())
code = code.padLeft(14, '0')
assert code.size() == 14
int sum = 0
code.eachWithIndex{ c, i ->
sum += c.toInteger() * ((i % 2 == 0) ? 3 : 1)
}
returnValue = sum % 10 == 0
}
return returnValue
}
def upc_validate(upc):
# check if upc is exactly 12 digits
upc = str(upc)
if len(upc) != 12 or len(list(filter(lambda x: 48 <= ord(x) <= 57, upc))) != 12:
return False
# validate CRC / check digit (sum of digits is a product of 10 after multiplying each odd digit by CRC)
digits = list(map(int, upc))
crc = digits[-1]
total = sum([digit if i & 1 else digit * crc for i, digit in enumerate(digits)])
return total % 10 == 0
基于Luciano的答案。
我移除了Linq依赖,因为我也需要在Java中使用它。将填充位数减少到14位,以便用于计算更长的ITF条码的校验位。
通过使用(i + code.Length % 2)
处理不均匀长度的代码,使得31313
模式对于不均匀长度的代码变为13131
。这样可以避免创建对象,并且在我的电脑上计算所有EAN-8代码的校验位只需134毫秒。
我知道问题是关于一个IsValidEan()
方法,但是如果你有一个带有方法的库,你可能仍然需要这个方法。在长度和其他检查后,IsValidEan()
应该调用这个方法进行校验位验证。
/// <summary>
/// Calculate check digit for UPC-A, EAN-13, ITF-14 (or any ITF)
/// </summary>
/// <param name="code">This should include the check digit (append a fake check digit if needed)</param>
/// <returns></returns>
public static char CalculateCheckDigit(string code)
{
// Don't include check digit in the sum (< code.Length - 1)
int sum = 0;
for (int i = 0; i < code.Length - 1; i++)
sum += (code[i] - '0') * (((i + code.Length % 2) % 2 == 0) ? 3 : 1);
return (char)((10 - (sum % 10)) % 10 + '0');
}
Java版本:
public static char CalculateCheckDigit(String code) {
int sum = 0;
for(int i = 0; i < code.length() - 1; i++)
sum += ((int)code.charAt(i) - (int)'0') * (((i + code.length() % 2) % 2 == 0) ? 3 : 1);
return (char)((10 - (sum % 10)) % 10 + (int)'0');
}
function DigitEan(cCodigo)
local cCode := AllTrim(cCodigo)
local nLen := Len(cCode)
local cc := 0
local i := 0
for i:=1 to nLen-1
cc+=(asc(substr(cCode,nLen-i,1))-48)*iif(i%2==0,1,3)
next
return ( (10-(cc%10))%10 )
private void button1_Click(object sender, EventArgs e)
{
string code = textBox1.Text;
string sBarcode = string.Empty;
sBarcode = IsValidGtin(code);
lblBarCode.Text = sBarcode;
}
public static string IsValidGtin(string code)
{
//if (code != (new Regex("[^0-9]")).Replace(code, ""))
//{
// // is not numeric
// return false;
//}
// pad with zeros to lengthen to 14 digits
switch (code.Length)
{
case 2:
code = code + "000000000";
break;
case 3:
code = code + "00000000";
break;
case 4:
code = code + "0000000";
break;
case 5:
code = code + "000000";
break;
case 6:
code = code + "00000";
break;
case 7:
code = code + "0000";
break;
case 8:
code = code + "000";
break;
case 9:
code = code + "00";
break;
case 10:
code = code + "0";
break;
case 11:
break;
case 12:
code = code.Substring(0, 11);
break;
//default:
// wrong number of digits
// return false;
}
// calculate check digit
int[] a = new int[12];
a[0] = int.Parse(code[0].ToString()) * 3;
a[1] = int.Parse(code[1].ToString());
a[2] = int.Parse(code[2].ToString()) * 3;
a[3] = int.Parse(code[3].ToString());
a[4] = int.Parse(code[4].ToString()) * 3;
a[5] = int.Parse(code[5].ToString());
a[6] = int.Parse(code[6].ToString()) * 3;
a[7] = int.Parse(code[7].ToString());
a[8] = int.Parse(code[8].ToString()) * 3;
a[9] = int.Parse(code[9].ToString());
a[10] = int.Parse(code[10].ToString()) * 3;
//a[11] = int.Parse(code[11].ToString());
//a[12] = int.Parse(code[12].ToString()) * 3;
int sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10];
string check = Convert.ToString((10 - (sum % 10)));
// evaluate check digit
// int last = int.Parse(code[13].ToString());
// return check == last;
code = code + check;
return code;
}