Estoy tratando de hacer las mismas matemáticas que en los lenguajes tipificados estáticamente, pero me da números diferentes si el argumento es grande.
function xorshiftmult(x) { x ^= x >> 12n x ^= x << 25n x ^= x >> 27n return BigInt.asUintN(64, x * 2685821657736338717n) }Números pequeños:
input/output 1n 5180492295206395165n 2n 10360984590412790330n 3n 15541476885619185495n 4n 4961046764852367761n 5n 4769895744586085492n 6n 15322031355265158091n 7n 15130880334998875822n 8n 9922093529704735522n 9n 15102585824911130687nGrandes números:
input/output 7292821753470094447n 4831377277631613306n 17517393223776413492n 8648459866934146562n 12871125787594255668n 10283147200615164616n 16549285201548370653n 6000770026373893856n 18260228909704403279n 13976674343699112182n 7574594482456054693n 16722430591553842838n 17620850200451425087n 15710702043522419077n 11252008783195621033n 12240320011096546170n 13791874522026752862n 7426906761295174006n 12869035004249813321n 1654853426672194495n(ir)
func xorshiftmult(x uint64) uint64 { x ^= x >> 12 x ^= x << 25 x ^= x >> 27 return x * 2685821657736338717 }Números pequeños:
input/output 1 5180492295206395165 2 10360984590412790330 3 15541476885619185495 4 4961046764852367761 5 4769895744586085492 6 15322031355265158091 7 15130880334998875822 8 9922093529704735522 9 15102585824911130687GRANDES números:
input/output 7292821753470094447 4375439080089995642 17517393223776413492 3385204219959375362 12871125787594255668 13047519269082376904 16549285201548370653 13622873389358370528 18260228909704403279 10325503129038119158 7574594482456054693 7461249648354733718 17620850200451425087 13330604890916407685 11252008783195621033 8666328877708335994 13791874522026752862 16881109032334662006 12869035004249813321 14233246107464520639Como puede ver, los números grandes son diferentes. ¿Pero por qué? ¿Que hice mal?
Debe sujetar el número en cada paso, no solo al final. De lo contrario, los bits que movió a la izquierda más allá del bit 64 volverán a aparecer cuando vuelva a cambiar a la derecha, mientras que en Go ya se habrían "caído por el precipicio".
Por ejemplo, si su entrada es 2 ^ 50, el primer paso le daría 2 ^ 50 + 2 ^ 38 y el segundo paso luego 2 ^ 50 + 2 ^ 38 + 2 ^ 75 + 2 ^ 63 (mientras que en Go obtendría solo 2^50+2^38+2^63 en ese punto), así que después del tercer paso obtendrías 2^50+2^38+ 2^75 +2^63+2^23+2^11+ 2^48 +2^36 (mientras que en Go no existirían 2^75 y 2^48) y después de fijar el resultado final es 2^50+2^38+2^63+2^23+2^11 + 2 ^ 48 + 2 ^ 36 - en Go, el 2 ^ 48 no estaría allí porque proviene de 2 ^ 75 en el segundo paso, que en Go ya se habría bloqueado y no podría haber introducido el 2 ^ 48 en el siguiente paso.
function xorshiftmult(x) { x = BigInt.asUintN(64, x ^ x >> 12n) x = BigInt.asUintN(64, x ^ x << 25n) x = BigInt.asUintN(64, x ^ x >> 27n) return x } Nota: Técnicamente, sería suficiente usar BigInt.asUintN solo en el paso << porque los pasos >> no pueden producir números más grandes, solo más pequeños. Lo haría de todos modos, por consistencia, pero si la velocidad es una preocupación, esto podría usarse en su lugar:
function xorshiftmult(x) { x ^= x >> 12n x = BigInt.asUintN(64, x ^ x << 25n) x ^= x >> 27n return x }