Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk menterjemah blok CRC32 ini dengan betul daripada Pergi ke JavaScript?

Bagaimana untuk menterjemah blok CRC32 ini dengan betul daripada Pergi ke JavaScript?

PHPz
PHPzke hadapan
2024-02-13 22:00:11831semak imbas

如何正确地将这个块 CRC32 从 Go 翻译为 JavaScript?

Dalam proses pembangunan merentas bahasa, kita sering menghadapi situasi di mana kita perlu menterjemah algoritma atau fungsi daripada satu bahasa ke bahasa lain. Dalam proses ini, terjemahan blok CRC32 adalah keperluan biasa. Walau bagaimanapun, menterjemah blok CRC32 ini daripada Pergi ke JavaScript bukanlah tugas yang mudah. Dalam artikel ini, editor PHP Xigua akan memperkenalkan cara menterjemah blok CRC32 ini dengan betul daripada Pergi ke JavaScript untuk membantu pembangun menyelesaikan masalah ini.

Kandungan soalan

Saya mempunyai fungsi ini:

package main

import (
    "fmt"
    "github.com/snksoft/crc"
)

var crctable *crc.table

func init() {
        params := crc.crc32
        params.finalxor = 0
        params.reflectout = false
        crctable = crc.newtable(params)
}

func crccalculateblock(data []byte) uint32 {

    if len(data)%4 > 0 {
        panic("block size needs to be a multiple of 4")
    }

    h := crc.newhashwithtable(crctable)

    var buf [4]byte
    for i := 0; i < len(data); i += 4 {
        buf[0] = data[i+3]
        buf[1] = data[i+2]
        buf[2] = data[i+1]
        buf[3] = data[i+0]
        h.update(buf[:])
    }

    return h.crc32()
}

func main() {
  data := []byte{1, 2, 3, 4, 5, 6, 7, 8}
    crc := crccalculateblock([]byte(data))
    fmt.printf("crc is 0x%04x\n", crc)
}

Hasilnya ialah: 0x948b389d

Saya cuba menterjemah ini kepada javascript tetapi saya kehilangan sesuatu:

var makeCRCTable = function(){
    var c;
    var crcTable = [];
    for(var n =0; n < 256; n++){
        c = n;
        for(var k =0; k < 8; k++){
            c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
        }
        crcTable[n] = c;
    }
    return crcTable;
}

var crc32 = function(u8array) {
    var crcTable = window.crcTable || (window.crcTable = makeCRCTable());
    var crc = 0 ^ (-1);

    for (var i = 0; i < u8array.length; i+=4 ) {
        crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i+3]) & 0xFF];
        crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i+2]) & 0xFF];
        crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i+1]) & 0xFF];
        crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i]) & 0xFF];
    }

    return (crc ^ (-1)) >>> 0;
};

console.log(crc32(Uint8Array.from([1,2,3,4,5,6,7,8])).toString(16))

Tetapi hasilnya berbeza. (46e32ed6)

Walaupun tanpa XOR akhir saya mendapat b91cd129

Bolehkah sesiapa menerangkan kepada saya bagaimana untuk membetulkan ini dan mengapa ini salah?

Penyelesaian

Terdapat dua perbezaan:

  1. perlaksanaan go telah dipanggil reflect (lihat https://www.php.cn/link/f23775b54b9e62e2d15498c3b9418630):

    if t.crcparams.reflectout != t.crcparams.reflectin {
        ret = reflect(ret, t.crcparams.width)
    }
    
  2. dalam

    go (finalxor0 (params.finalxor = 0) 而在 js 中是 -1kembali (crc ^ (-1)) phpcngt phpcn>> 0;phpcnendc phpcn)

Berikut ialah pelaksanaan js yang dikemas kini yang menghasilkan cincangan yang sama.

var makeCRCTable = function () {
  var c;
  var crcTable = [];
  for (var n = 0; n < 256; n++) {
    c = n;
    for (var k = 0; k < 8; k++) {
      c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
    }
    crcTable[n] = c;
  }
  return crcTable;
};

var crc32 = function (u8array) {
  var crcTable = window.crcTable || (window.crcTable = makeCRCTable());
  var crc = 0 ^ -1;

  for (var i = 0; i < u8array.length; i += 4) {
    crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i + 3]) & 0xff];
    crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i + 2]) & 0xff];
    crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i + 1]) & 0xff];
    crc = (crc >>> 8) ^ crcTable[(crc ^ u8array[i]) & 0xff];
  }

  crc = reverseBits(crc, 32);

  return (crc ^ 0) >>> 0;
};

function reverseBits(integer, bitLength) {
  if (bitLength > 32) {
    throw Error(
      'Bit manipulation is limited to <= 32 bit numbers in JavaScript.'
    );
  }

  let result = 0;
  for (let i = 0; i < bitLength; i++) {
    result |= ((integer >> i) & 1) << (bitLength - 1 - i);
  }

  return result >>> 0; // >>> 0 makes it unsigned even if bit 32 (the sign bit) was set
}

console.log(crc32(Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8])).toString(16));

Atas ialah kandungan terperinci Bagaimana untuk menterjemah blok CRC32 ini dengan betul daripada Pergi ke JavaScript?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam