【问题标题】:Translate CRC alrgorythm from C to PHP将 CRC 算法从 C 翻译成 PHP
【发布时间】:2023-03-06 15:23:01
【问题描述】:

已解决

我在 C 上有以下代码,我必须在 PHP 上编写它

const U16 crc_table[16] = {
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
};

U16 CalculateCrc(char *data, U32 len) {
    U32 i;
    U16 crc = 0;

    while (len--) {
        i = (crc >> 12) ^ (*data >> 4);
        crc = crc_table[i & 0x0F] ^ (crc << 4);
        i = (crc >> 12) ^ (*data >> 0);
        crc = crc_table[i & 0x0F] ^ (crc << 4);
        data++;
    }
    return (crc & 0xFFFF);
}

到目前为止,在基本的逻辑翻译中,我是这样做的:

public function crc($data){

        $i = 0;
        $crc = 0;

        /* @var $crc_table array */
        $crc_table = array
            (
                0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
                0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
            );

        for($a = 0; $a < strlen($data); $a++){
            $i = (($crc >> 12) ^ ($data[$a] >> 4));
            $crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
            $i = (($crc >> 12) ^ $data[$a]);
            $crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
        }



        return ($crc & 0xFFFF);

    }

结果绝不匹配,我不是这种事情的专家。有什么建议吗?


编辑

感谢“娇气的ossifrage”! 根据您的帮助,我现在正在使用此功能:

private function crc($data){

        $i = 0;
        $crc = 0;

        $crc_table = array
            (
                0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
                0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
            );

        $data = hex2bin($data);
        $l = 0;
        while($l < strlen($data)){

            $byte = $data[$l];
            $i = (($crc >> 12) ^ (ord($byte) >> 4));
            $crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
            $i = (($crc >> 12) ^ (ord($byte) >> 4));
            $crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
            $l++;
        }

        return ($crc & 0xFFFF);

    }

我正在使用“Hello world”作为十六进制“48656C6C6F20776F726C64”对其进行测试。 在 C 上我得到 37278 和 56062 以上的 php 函数。

现在有什么线索吗?


编辑

好吧,我的错……问题已经解决了,但经过这么多测试,我自己都搞糊涂了。

这是我的第一个代码版本,带有“squeamish ossifrage”的建议更正:

$byte = $data[$l];
$i = (($crc >> 12) ^ (ord($byte) >> 4));
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
$i = (($crc >> 12) ^ **ord($byte));**
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
$l++;

谢谢!

【问题讨论】:

  • 不要忘记 php 的整数在内部总是 32 位或 64 位。 16 位 C int 可能发生的位溢出不会在 php 中发生,因为有很多“额外”位来保存溢出。
  • 您是否考虑过使用内置的 CRC 计算? php.net/manual/en/function.crc32.php
  • @EricJ。是的,但我不能,因为我必须与 C 算法兼容,而我无法更改。

标签: php c crc


【解决方案1】:

您的代码不工作,因为您正在计算整数和字符串变量的异或积:

$i = (($crc >> 12) ^ ($data[$a] >> 4));

这里$data[$a] 是输入数据的子字符串。您应该使用ord() 将其转换为整数:

$i = (($crc >> 12) ^ (ord($data[$a]) >> 4));

编辑:通过对您的 PHP 代码进行此更改,字符串 Hello, world! 在两个函数中都散列为 31454。)

【讨论】:

  • 不错!如果我的输入是 16 个基本字符串并且我将 (ord($data[$a]) 替换为 intval($data[$a].$data[$a++],16) 它应该可以工作,对吧?
  • 不,这行不通。你是说$data[$a].$data[$a+1](后面跟$a += 2)吗?我希望hex2bin() 可以更快地将十六进制数据转换为二进制。
  • 是的,我是认真的。好,我会用 hex2bin 试试!谢谢。
  • 刚刚根据您的帮助编辑了问题。很高兴您能再看看这个。
猜你喜欢
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多