Heim  >  Artikel  >  Backend-Entwicklung  >  Wie übersetzt man diesen Block CRC32 richtig von Go zu JavaScript?

Wie übersetzt man diesen Block CRC32 richtig von Go zu JavaScript?

PHPz
PHPznach vorne
2024-02-13 22:00:11873Durchsuche

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

Im Prozess der sprachübergreifenden Entwicklung stoßen wir häufig auf Situationen, in denen wir einen Algorithmus oder eine Funktion von einer Sprache in eine andere übersetzen müssen. In diesem Prozess ist die Block-CRC32-Übersetzung eine häufige Anforderung. Allerdings ist die Übersetzung dieses CRC32-Blocks von Go nach JavaScript keine leichte Aufgabe. In diesem Artikel stellt der PHP-Editor Xigua vor, wie dieser Block CRC32 von Go nach JavaScript korrekt übersetzt wird, um Entwicklern bei der Lösung dieses Problems zu helfen.

Frageninhalt

Ich habe diese Funktion in go:

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)
}

Das Ergebnis ist: 0x948b389d

Ich versuche, dies in Javascript zu übersetzen, aber mir fehlt etwas:

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))

Aber die Ergebnisse sind unterschiedlich. (46e32ed6)

Auch ohne das letzte XOR erhalte ich b91cd129

Kann mir jemand erklären, wie ich das korrigieren kann und warum das falsch ist?

Lösung

Es gibt zwei Unterschiede:

    Die
  1. go-Implementierung wurde aufgerufen reflect (siehe https://www.php.cn/link/f23775b54b9e62e2d15498c3b9418630):

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

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

    go

Hier ist die aktualisierte js-Implementierung, die denselben Hash generiert.

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));

Das obige ist der detaillierte Inhalt vonWie übersetzt man diesen Block CRC32 richtig von Go zu JavaScript?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen