Heim > Artikel > Backend-Entwicklung > Wie übersetzt man diesen Block CRC32 richtig von Go zu 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.
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?
Es gibt zwei Unterschiede:
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) }
return (crc ^ (-1)) phpcngt phpcn>> 0;phpcnendc phpcn)finalxor
是 0
(params.finalxor = 0
) 而在 js 中是 -1
in
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!