【问题标题】:EAN 8 : How to calculate checksum digit?EAN 8:如何计算校验和数字?
【发布时间】:2010-11-11 07:41:22
【问题描述】:

我需要以编程方式创建 EAN 8 条形码。 我搜索了一个算法来计算校验和数字。

【问题讨论】:

    标签: barcode checksum


    【解决方案1】:

    该算法已在此wikipedia article on EAN 中介绍,请注意 EAN-8 的计算方式与 EAN-13 相同。

    这是来自http://www.barcodeisland.com/ean8.phtml 的一个工作示例:

    假设我们希望对 7 位消息“5512345”进行编码,我们将按以下方式计算校验和:

    Barcode          5     5     1     2     3     4     5
    Odd/Even Pos?    O     E     O     E     O     E     O
    Weighting        3     1     3     1     3     1     3
    Calculation    5*3   5*1   1*3   2*1   3*3   4*1   5*3
    Weighted Sum    15     5     3     2     9     4    15
    

    总数为 15 + 5 + 3 + 2 + 9 + 4 + 15 = 53。7 必须与 53 相加才能产生可​​被 10 整除的数,因此校验和数字为 7,完成的条码值为“55123457”。

    string code="55123457";
    
    int sum1 = code[1] + code[3] + code[5] 
    int sum2 = 3 * (code[0] + code[2] + code[4] + code[6]);
    int checksum_value = sum1 + sum2;
    
    int checksum_digit = 10 - (checksum_value % 10);
    if (checksum_digit == 10) 
        checksum_digit = 0;
    

    【讨论】:

      【解决方案2】:
      int checkSum(const std::vector<int>& code) const
      {
          if (code.size() < 8) return false;
      
          for( SIZE_T i = 0; i< code.size(); i++ )
          {
              if( code[i] < 0 ) return false;
          }
      
          int sum1 = code[1] + code[3] + code[5] 
          int sum2 = 3 * (code[0] + code[2] + code[4] + code[6]);
      
          int checksum_value = sum1 + sum2;
          int checksum_digit = 10 - (checksum_value % 10);
          if (checksum_digit == 10) checksum_digit = 0;
      
          return checksum_digit;
      }
      

      【讨论】:

      • 这是不正确的 - sum1 应该是 (code[1] + code[3] + code[5]),sum2 应该是 3 * (code[0] + code[2] + code[ 4] + 代码[6])
      • 好的。仅使用 EAN13 进行测试。似乎 EAN8 和 EAN13 中的起始权重不同...
      • 位数是从右数,所以8是偶数,13是奇数,所以权重不同。感谢您的编辑,已删除反对票!
      • 好答案 - 我会尝试在 VBA for Excel 上编写它
      【解决方案3】:

      抱歉重新打开

      JAVA 版本

      public int checkSum(String code){
              int val=0;
              for(int i=0;i<code.length();i++){
                  val+=((int)Integer.parseInt(code.charAt(i)+""))*((i%2==0)?1:3);
              }
      
              int checksum_digit = 10 - (val % 10);
              if (checksum_digit == 10) checksum_digit = 0;
      
              return checksum_digit;
          }
      

      【讨论】:

      • 实际上对我来说它适用于 EAN13 但不适用于 EAN8
      • 权重 1 和 3 混合?切换它们。
      【解决方案4】:

      用 C# 版本重新唤醒:

          public static bool IsValidEan13(string eanBarcode)
          {
              return IsValidEan(eanBarcode, 13);
          }
      
          public static bool IsValidEan12(string eanBarcode)
          {
              return IsValidEan(eanBarcode, 12);
          }
      
          public static bool IsValidEan14(string eanBarcode)
          {
              return IsValidEan(eanBarcode, 14);
          }
      
          public static bool IsValidEan8(string eanBarcode)
          {
              return IsValidEan(eanBarcode, 8);
          }
      
          private static bool IsValidEan(string eanBarcode, int length)
          {
              if (eanBarcode.Length != length) return false;
              var allDigits = eanBarcode.Select(c => int.Parse(c.ToString(CultureInfo.InvariantCulture))).ToArray();
              var s = length%2 == 0 ? 3 : 1;
              var s2 = s == 3 ? 1 : 3;
              return allDigits.Last() == (10 - (allDigits.Take(length-1).Select((c, ci) => c*(ci%2 == 0 ? s : s2)).Sum()%10))%10;
          }
      

      【讨论】:

        【解决方案5】:

        这里是 EAN13 的 Java 版本

         private int calcChecksum(String first12digits) {
            char[] char12digits = first12digits.toCharArray();
            int[] ean13 = {1,3};
            int sum = 0;
            for(int i = 0 ; i<char12digits.length; i++){
                sum += Character.getNumericValue(char12digits[i]) * ean13[i%2];
            }
        
            int checksum = 10 - sum%10;
            if(checksum == 10){
                checksum = 0;
            }
        
            return checksum;
        }
        

        【讨论】:

          【解决方案6】:
          class GTIN(object):
          
              def __init__(self, barcode=''):
                  self.barcode = barcode
          
              def __checkDigit(self, digits):
                      total = sum(digits) + sum(map(lambda d: d*2, digits[-1::-2]))
                      return (10 - (total % 10)) % 10
          
              def validateCheckDigit(self, barcode=''):
                  barcode = (barcode if barcode else self.barcode)
                  if len(barcode) in (8,12,13,14) and barcode.isdigit():
                      digits = map(int, barcode)
                      checkDigit = self.__checkDigit( digits[0:-1] )
                      return checkDigit == digits[-1]
                  return False
          
              def addCheckDigit(self, barcode=''):
                  barcode = (barcode if barcode else self.barcode)
                  if len(barcode) in (7,11,12,13) and barcode.isdigit():
                      digits = map(int, barcode)
                      return barcode + str(self.__checkDigit(digits))
                  return ''
          

          【讨论】:

            【解决方案7】:

            这是 EAN13 的 MySQL 版本:

                SET @first12digits="123456789012";
                SELECT @first12digits,
            IF (
                (@check:=10-MOD(
                    (CAST(SUBSTRING(@first12digits, 1, 1) AS DECIMAL))+
                    (CAST(SUBSTRING(@first12digits, 2, 1) AS DECIMAL) * 3)+
                    (CAST(SUBSTRING(@first12digits, 3, 1) AS DECIMAL))+
                    (CAST(SUBSTRING(@first12digits, 4, 1) AS DECIMAL) * 3)+
                    (CAST(SUBSTRING(@first12digits, 5, 1) AS DECIMAL))+
                    (CAST(SUBSTRING(@first12digits, 6, 1) AS DECIMAL) * 3)+
                    (CAST(SUBSTRING(@first12digits, 7, 1) AS DECIMAL))+
                    (CAST(SUBSTRING(@first12digits, 8, 1) AS DECIMAL) * 3)+
                    (CAST(SUBSTRING(@first12digits, 9, 1) AS DECIMAL))+
                    (CAST(SUBSTRING(@first12digits, 10, 1) AS DECIMAL) * 3)+
                    (CAST(SUBSTRING(@first12digits, 11, 1) AS DECIMAL))+
                    (CAST(SUBSTRING(@first12digits, 12, 1) AS DECIMAL) * 3)
                ,10)) = 10, 0, @check
                ) AS checkDigit;
            

            有一个错误。如果计算结果 = 10,则检查数字 = 0。
            下面是 EAN14 的更好版本。

            
            
                SET @first13digits="1234567890123";
                SELECT @txCode13:=@first13digits,
                    @iCheck := (
                        10 - (
                        (
                            MID(@txCode13, 2, 1) +
                            MID(@txCode13, 4, 1) +
                            MID(@txCode13, 6, 1) +
                            MID(@txCode13, 8, 1) +
                            MID(@txCode13, 10, 1) +
                            MID(@txCode13, 12, 1)
                        ) + (
                            MID(@txCode13, 1, 1) +
                            MID(@txCode13, 3, 1) +
                            MID(@txCode13, 5, 1) +
                            MID(@txCode13, 7, 1) +
                            MID(@txCode13, 9, 1) +
                            MID(@txCode13, 11, 1) +
                            MID(@txCode13, 13, 1)
                            ) * 3 ) % 10
                        ) AS iCheck,
                    @iCheckDigit := IF(@iCheck = 10, 0, @iCheck) AS checkDigit,
                    CONCAT(@t
            
            xCode13, CAST(@iCheckDigit AS CHAR)) AS EAN14WithCheck
            

            【讨论】:

            • 有一个错误。如果计算结果 = 10,则校验位为 0。
            【解决方案8】:

            Java 版本:

            效果很好

            public static int checkSum(String code){
                    int val=0;
                    for(int i=0; i<code.length()-1; i++){
                        val+=((int)Integer.parseInt(code.charAt(i)+""))*((i%2==0)?1:3);
                    }
            
                    int checksum_digit = (10 - (val % 10)) % 10;
            
                    return checksum_digit;
                }
            

            【讨论】:

            • 对于“1234567”返回“5”。正确的校验和是“0”
            【解决方案9】:

            基于 Najoua Mahi 的 Java 函数的 Python EAN13 校验位计算:

            def generateEAN13CheckDigit(self, first12digits):
                charList = [char for char in first12digits]
                ean13 = [1,3]
                total = 0
                for order, char in enumerate(charList):
                    total += int(char) * ean13[order % 2]
            
                checkDigit = 10 - total % 10
                if (checkDigit == 10):
                    return 0
                return checkDigit
            

            【讨论】:

              【解决方案10】:

              这适用于 EAN 13EAN8

              public static String generateEAN(String barcode) {
                  int first = 0;
                  int second = 0;
              
                  if(barcode.length() == 7 || barcode.length() == 12) {
              
                      for (int counter = 0; counter < barcode.length() - 1; counter++) {
                          first = (first + Integer.valueOf(barcode.substring(counter, counter + 1)));
                          counter++;
                          second = (second + Integer.valueOf(barcode.substring(counter, counter + 1)));
                      }
                      second = second * 3;
                      int total = second + first;
                      int roundedNum = Math.round((total + 9) / 10 * 10);
              
                      barcode = barcode + String.valueOf(roundedNum - total);
                  }
                  return barcode;
              }
              

              【讨论】:

                【解决方案11】:

                今天我需要一个PHP版本,我记得这个页面并从Java版本复制。谢谢。

                function getEAN13($txEan12)
                    {
                    $iVal=0;
                
                    for($i=0; $i<strlen($txEan12); $i++)
                        {
                        $iSingleCharVal = intval(substr($txEan12, $i, 1));      // extract value of one char
                        $iSingleCharMult = $iSingleCharVal * ($i%2==0 ? 1 : 3); // calculate depending from position
                        $iVal+= $iSingleCharMult;   // sum
                        }
                
                    $iCheckDigit = 10 - ($iVal % 10);
                    if ($iCheckDigit == 10) $iCheckDigit = 0;
                    return $txEan12 . $iCheckDigit;
                    }
                

                【讨论】:

                  【解决方案12】:

                  这是我在 VFP (Visual FoxPro 9) 中为 EAN-8 和 EAN-13 编写的代码

                  Lparameters lcBarcode,llShowErrorMessage
                  
                  If Vartype(m.lcBarcode)<>'C'
                      If m.llShowErrorMessage
                          MessageBox([Type of parameter is incorect!],0+16,[Error Message])
                      EndIf 
                      Return .f.
                  EndIf 
                  
                  If Len(Chrtran(Alltrim(m.lcBarcode),[0123456789],[]))>0
                      If m.llShowErrorMessage
                          MessageBox([Provided barcode contains invalid characters!],0+16,[Error Message])
                      EndIf 
                      Return .f.
                  EndIf 
                  
                  If Len(Alltrim(m.lcBarcode))=0
                      If m.llShowErrorMessage
                          MessageBox([The length of provided barcode is 0 (zero)!],0+16,[Error Message])
                      EndIf 
                      Return .f.
                  EndIf 
                  
                  If !InList(Len(Alltrim(m.lcBarcode)),8,13)
                      If m.llShowErrorMessage
                          MessageBox([Provided barcode is not an EAN-8 or EAN-13 barcode!],0+16,[Error Message])
                      EndIf 
                      Return .f.
                  EndIf 
                  
                  Local lnCheck as Integer, lnSum as Integer, lnOriginalCheck as Integer,jj as Integer
                  
                  jj=0
                  lnSum=0
                  m.lnOriginalCheck = Cast(Right(Alltrim(m.lcBarcode),1) as Integer)
                  m.lcBarcode = Left(Alltrim(m.lcBarcode),Len(Alltrim(m.lcBarcode))-1) 
                  
                  For ii = Len(m.lcBarcode) to 1 step -1
                      jj=jj+1
                      lnSum = lnSum + Cast(Substr(m.lcBarcode,ii,1) as Integer) * Iif(Mod(jj,2)=0,1,3)
                  Next 
                  lnCheck = 10-Mod(lnSum,10)
                  lnCheck = Iif(lnCheck =10,0,lnCheck)
                  
                  Return (lnCheck = lnOriginalCheck)
                  

                  【讨论】:

                    【解决方案13】:

                    EAN-8EAN-13

                    的 JavaScript 版本
                    function checksum(code) {
                        const sum = code.split('').reverse().reduce((sum, char, idx) => {
                            let digit = Number.parseInt(char);
                            let weight = (idx + 1) % 2 === 0 ? 1 : 3;
                            let partial = digit * weight;
                            return sum + partial;
                        }, 0);
                    
                        const remainder = sum % 10;
                        const checksum = remainder ? (10 - remainder) : 0;
                    
                        return checksum;
                    }
                    

                    【讨论】:

                    • function checksum(code){ return (10 - (code.split('').reduce((s, e, i) =&gt; { return s + parseInt(e) * ((i%2==0)?1:3) },0) % 10)) % 10; }
                    【解决方案14】:

                    迷你 Javascript 版本

                    function checksum(code){
                       return (10 - (code.split('').reduce((s, e, i) => { return s + parseInt(e) * ((i%2==0)?1:3) },0) % 10)) % 10;
                      }
                    

                    【讨论】:

                      【解决方案15】:
                      =INT(CONCAT([@Code],MOD(10 - MOD((MID([@Code], 2, 1) + MID([@Code], 4, 1) + MID([@Code], 6, 1)) + (3*(MID([@Code], 1, 1) + MID([@Code], 3, 1) + MID([@Code], 5, 1) + MID([@Code], 7, 1))),10), 10)))
                      

                      上述公式将计算校验字符,无需使用宏或更改为XLSM

                      注意:仅适用于 EAN-8。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-02-04
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2017-04-07
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多