Based on my understanding of how check digits are supposed to be calculated for barcodes, namely:
0) Sum the values of all the characters at odd indexes (1, 3, etc.)
1) Multiply that sum by 3
2) Sum the values of all the characters at even indexes (o, 2, etc.)
3) Combine the two sums from steps 1 and 2
4) Calculate the check digit by subtracting the modulus 10 of the combined sum from 10
So for example, with a barcode "04900000634" the combined sum is 40*; To get the check sum, the modulus (40 % 10) == 0, and then 10 - 0 == 10.
- Odd characters == 7; X3 = 21; Even characters == 19, for a combined sum of 40.
Since a check digit is a scalar value, what if the result of the check digit calculation is 10? Does one use "0" or "1"?
Here is the code I'm using (thanks to some help from here: Why does 1 + 0 + 0 + 0 + 3 == 244?); I'm assuming that the formula pseudocoded above applies regardless of the length (8 chars, 12 chars, etc.) and type (128, EAN8, EAN12, etc.) of the barcode.
private void button1_Click(object sender, EventArgs e)
{
string barcodeWithoutCzechSum = textBox1.Text.Trim();
string czechSum = GetBarcodeChecksum(barcodeWithoutCzechSum);
string barcodeWithCzechSum = string.Format("{0}{1}", barcodeWithoutCzechSum, czechSum);
label1.Text = barcodeWithCzechSum;
}
public static string GetBarcodeChecksum(string barcode)
{
int oddTotal = sumOddVals(barcode);
int oddTotalTripled = oddTotal*3;
int evenTotal = sumEvenVals(barcode);
int finalTotal = oddTotalTripled + evenTotal;
int czechSum = 10 - (finalTotal % 10);
return czechSum.ToString();
}
private static int sumEvenVals(string barcode)
{
int cumulativeVal = 0;
for (int i = 0; i < barcode.Length; i++)
{
if (i%2 == 0)
{
cumulativeVal += Convert.ToInt16(barcode[i] - '0');
}
}
return cumulativeVal;
}
private static int sumOddVals(string barcode)
{
int cumulativeVal = 0;
for (int i = 0; i < barcode.Length; i++)
{
if (i % 2 != 0)
{
cumulativeVal += Convert.ToInt16(barcode[i] - '0');
}
}
return cumulativeVal;
}
UPDATE
The calculator here: http://www.gs1us.org/resources/tools/check-digit-calculator claims that the check digit for 04900000634 is 6
How is that being arrived at?
UPDATE 2
This http://www.gs1.org/barcodes/support/check_digit_calculator revises my understanding of the last part of the equation/formula, where it says, "Subtract the sum from nearest equal or higher multiple of ten = 60- 57 = 3 (Check Digit)"
So, in the case of 04900000634, the combined sum is 40. Based on that formula, the "nearest equal or higher multiple of ten" of 40 is 40, so 40-40=0, and I would expect that to be the check sum (not 6)...so, still confused...
UPDATE 3
I'm not understanding why yet, but mike z's comment must be correct, because when I reverse the "==" and "!=" logic in the sumOddVals() and sumEvenVals() functions, my results correspond to those generated by http://www.gs1us.org/resources/tools/check-digit-calculator
UPDATE 4
Apparently, based on http://en.wikipedia.org/wiki/European_Article_Number, the powers that be behind check digit calculations don't consider the first position to be position 0, but position 1. Confusing for developers, trained to see the first item as residing at index 0, not 1!
The check digit is always last.
Starting with the digit immediately to the left of the check digit and moving LEFT, sum each digit, applying a weight of 3 and 1 alternately.
The check digit is then the number which needs to be added to produce a result that is a multiple of 10.
This works for ALL EAN/UPC codes - UPC-E, EAN-8 (which is all valid 8-digit codes except those whoch start 0,6 or 7) UPC-A (12-digit), EAN-13, EAN-14 (sometimes call "TUN" or "Carton" codes) and SSCCs (actually 18-digit, but implemented as part of the EAN128 standard with an AI of '00', misleading some into believing they're 20-digit codes)
When UPC-E was introduced, the original scheme was [language][company][product][check]. 0,6 and 7 were assigned to English and the remainder unassigned. [company] and [product] were variable-length with total 6 digits; short company numbers for companies with many products, long for companies with few products.
EAN used the remainder of the numbers, but assigned [country][company][product][check] where country was 2-digit.
That system soon ran out of puff, but is still occasionally assigned for very small products - and the original products that had numbers before UPC-A/EAN-13 was introduced.
UPC-A used the same schema as UPC-E, but lost the reference to 'language'. 0,6 and 7 were assigned to US/Canada. The company+product was extended to 10 digits.
EAN-13 extended the scheme to 13 digits, 2 for country, 10 for company+product, 1 to check. UPC-A was compatible by prefixing a leading "0".
By implementing the 13-digit scheme, US companies could track each of these codes and UPC-As did not need to be issued on products that already had an EAN-13 assigned. This was scheduled for completion about 8 years ago, but some companies still lag behind.
EAN-14s are used for carton outers. The leading digit is normall referred to as a "Trade Unit Identifier/Number" Hence the entire code is sometimes called a TUN. At first, there was an attempt to codify the leading digit (1=1doz, 2=2doz, etc.) but this was soon abandoned. Most companies use the number as a packaging level (1=cluster of individual items, 2=tray of clusters, 3=box of trays - depending on each company's preference. 9 is reserved. Not a good idea to use 0 (though some companies have) since it produces the same check-digit as the 13-digit code. I've used this for EAN128 codes bearing the batch number on non-retail goods; AI=01;EAN-14 (=EAN13 with TUN=0);AI=10;batch-number.
SSCCs are another can of worms. They're 18-digit - the first digit was originally used as a logistical descriptor, then there's the country-code, manufacturer-code and package-number with a check-digit. Originally, "3" meant an "external" pallet and "4" an "Internal" pallet, but this fell into disuse as impractical as an "Internal" pallet then has to be re-numbered if it gets sent "outside" and vice-versa.
And of course 2-digit country-codes have been supplanted by 3-digit as more countries have adopted the system.