【问题标题】:How can I calculate Longitudinal Redundancy Check (LRC)?如何计算纵向冗余校验 (LRC)?
【发布时间】:2012-09-29 17:32:10
【问题描述】:

我已经尝试过来自维基百科的示例:http://en.wikipedia.org/wiki/Longitudinal_redundancy_check

这是 lrc (C#) 的代码:

/// <summary>
/// Longitudinal Redundancy Check (LRC) calculator for a byte array. 
/// ex) DATA (hex 6 bytes): 02 30 30 31 23 03
///     LRC  (hex 1 byte ): EC    
/// </summary> 
public static byte calculateLRC(byte[] bytes)
{
    byte LRC = 0x00;
    for (int i = 0; i < bytes.Length; i++)
    {
        LRC = (LRC + bytes[i]) & 0xFF; 
    }
    return ((LRC ^ 0xFF) + 1) & 0xFF;
}   

它说结果是“EC”,但我得到“71”,我做错了什么?

谢谢。

【问题讨论】:

  • 那甚至不应该编译。一个字节上的数学把它变成一个 int。
  • 如果维基百科错了怎么办? C# 似乎已经更改了很多次,也更改了所使用的算法(它曾经是所有字节的简单异或,顺便说一下,它也没有给出 EC 作为答案)。
  • 另外,通过将结果写入十进制,您只能使用此输入从该代码中获得 71,在这种情况下,即使您得到的是,您也永远不会看到 EC答案(你会看到 236)
  • 可能值得注意的是,LRC 一词本身是模棱两可的,被不同的人用来描述两种不同的算法:en.wikipedia.org/wiki/Talk%3ALongitudinal_redundancy_check。如果您要检查损坏的字节,那么 XOR 算法是最简单的,应该可以解决问题。此外,显然 Wikipedia 的算法或预期结果都不正确。

标签: c# checksum parity


【解决方案1】:

我创建这个是为了让 Arduino 理解算法(当然它不是以最有效的方式编写的)

String calculateModbusAsciiLRC(String input)
{
  //Refer this document http://www.simplymodbus.ca/ASCII.htm

  if((input.length()%2)!=0) { return "ERROR COMMAND SHOULD HAVE EVEN NUMBER OF CHARACTERS"; } 
 // Make sure to omit the semicolon in input string and input String has even number of characters

   byte byteArray[input.length()+1];
   input.getBytes(byteArray, sizeof(byteArray));
    byte LRC = 0;
    for (int i = 0; i <sizeof(byteArray)/2; i++)
    {
      // Gettting the sum of all registers
     uint x=0;
     if(47<byteArray[i*2] && byteArray[i*2] <58) {x=byteArray[i*2] -48;}
     else { x=byteArray[i*2] -55;     }
       uint y=0;
     if(47<byteArray[i*2+1] && byteArray[i*2+1] <58) {y=byteArray[i*2+1] -48;}
     else { y=byteArray[i*2+1] -55;     }
     LRC  += x*16 + y;
    }   
    LRC = ~LRC + 1;   // Getting twos Complement
    String checkSum = String(LRC, HEX);
    checkSum.toUpperCase(); // Converting to upper case eg: bc to BC - Optional somedevices are case insensitve 
    return checkSum;
} 

【讨论】:

    【解决方案2】:

    如果有人想从字符串中获取 LRC 字符:

        public static char CalculateLRC(string toEncode)
        {
            byte[] bytes = Encoding.ASCII.GetBytes(toEncode);
            byte LRC = 0;
            for (int i = 0; i < bytes.Length; i++)
            {
                LRC ^= bytes[i];
            }
            return Convert.ToChar(LRC);
        }
    

    【讨论】:

      【解决方案3】:

      猜猜这个看起来更酷;)

      public static byte calculateLRC(byte[] bytes)
      {
          return bytes.Aggregate<byte, byte>(0, (x, y) => (byte) (x^ y));
      }
      

      【讨论】:

        【解决方案4】:

        我意识到这个问题已经很老了,但我很难弄清楚如何做到这一点。它现在正在工作,所以我想我应该粘贴代码。就我而言,校验和需要以 ASCII 字符串形式返回。

        public function getLrc($string)
        {
            $LRC = 0;
            // Get hex checksum.
            foreach (str_split($string, 1) as $char) {
                $LRC ^= ord($char);
            }
            $hex = dechex($LRC);
            // convert hex to string
            $str = '';
            for($i=0;$i<strlen($hex);$i+=2) $str .= chr(hexdec(substr($hex,$i,2)));
            return $str;
        }
        

        【讨论】:

        • 这个例子是php,问题是C#
        【解决方案5】:

        修正后的维基百科版本如下:

        private byte calculateLRC(byte[] b)
            {
                byte lrc = 0x00;
                for (int i = 0; i < b.Length; i++)
                {
                    lrc = (byte)((lrc + b[i]) & 0xFF);
                }
                lrc = (byte)(((lrc ^ 0xff) + 2) & 0xFF);
                return lrc;
            }
        

        【讨论】:

        • 我知道这有点像死神评论,但其中一些操作是不必要的。例如,另外,结果的低位不依赖于高位,所以你不需要为每个字节做&amp; 0xff,你可以在不改变结果的情况下最后做一次。转换为 byte 甚至会使最后一个 &amp; 0xff 变得多余。
        【解决方案6】:

        这是一个清理后的版本,它不会执行所有那些无用的操作(而不是每次都丢弃高位,而是最终一次性丢弃它们),它给出了您观察到的结果。这是使用加法的版本,但最后有一个否定 - 还不如减去并跳过否定。即使在溢出的情况下,这也是一个有效的转换。

        public static byte calculateLRC(byte[] bytes)
        {
            int LRC = 0;
            for (int i = 0; i < bytes.Length; i++)
            {
                LRC -= bytes[i];
            }
            return (byte)LRC;
        }
        

        这是另一种 LRC(一个简单的字节异或)

        public static byte calculateLRC(byte[] bytes)
        {
            byte LRC = 0;
            for (int i = 0; i < bytes.Length; i++)
            {
                LRC ^= bytes[i];
            }
            return LRC;
        }
        

        在这种情况下,无论是代码(无法编译)还是预期结果,维基百科都是错误的。

        【讨论】:

        • @AlexxPerez 也许这两种方法都没有.. 它真的没有记录它使用什么样的 LRC 吗?
        • 也许它使用了xor方法并跳过了第一个字节,你会得到4B。
        猜你喜欢
        • 2015-05-17
        • 2021-12-11
        • 2011-09-11
        • 1970-01-01
        • 2015-06-16
        • 1970-01-01
        • 1970-01-01
        • 2016-10-20
        • 2015-12-04
        相关资源
        最近更新 更多