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

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

PHPz
Freigeben: 2024-02-13 22:00:11
nach vorne
908 Leute haben es durchsucht

如何正确地将这个块 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)
}
Nach dem Login kopieren

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))
Nach dem Login kopieren

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)
    }
    
    Nach dem Login kopieren
  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));
Nach dem Login kopieren

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!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage