parselong number long hexadecimal floats float javascript integer overflow

long - number javascript



Resultados enteros de la matemática entera de JavaScript (3)

Cuando un entero en javascript es demasiado grande para caber en un valor de 32 bits, algunos navegadores lo convertirán en un punto flotante. Como el valor de los puntos flotantes solo se guarda con una precisión limitada, puede producirse cierto redondeo en los valores grandes.

Solo intento implementar un simple RNG en JS.

Lo que sucede es que javascript evalúa 119106029 * 1103515245 para ser 131435318772912110 lugar de 131435318772912105 . Sabemos que está mal ya que dos números impares multiplicados no dan un número par.

¿Alguien sabe qué pasa? Solo quiero un RNG repetible confiable, y debido a estos valores incorrectos no puedo obtener resultados que coincidan con mi implementación de C de la misma cosa.


Según el estándar ECMAScript, todos los números en JavaScript son números de coma flotante (IEEE 754 de 64 bits).

Sin embargo, todos los enteros de 32 bits se pueden representar exactamente como números de coma flotante. Puede forzar un resultado a 32 bits utilizando el operador de bit a bit apropiado, como este:

x = (a * b) >>> 0; // force to unsigned int32 x = (a * b) | 0; // force to signed int32

Raro, pero ese es el estándar.

(Por cierto, este comportamiento de redondeo es uno de los "errores" informados con más frecuencia contra el motor de JavaScript de Firefox. Parece que se ha informado 3 veces en lo que va del año ...)

En cuanto a los números aleatorios reproducibles en JavaScript, el punto de referencia V8 usa esto:

// To make the benchmark results predictable, we replace Math.random // with a 100% deterministic alternative. Math.random = (function() { var seed = 49734321; return function() { // Robert Jenkins'' 32 bit integer hash function. seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; return (seed & 0xfffffff) / 0x10000000; }; })();


Si se hace en C / C ++ (doble), los últimos números serán ... 112 en lugar de 105 (que es correcto). Si se realiza con ''doble largo'', el resultado será el esperado (... 105). Así que parece que el intérprete de Javascript convierte los números a 8 bytes byte internamente, realiza el cálculo y realiza un redondeo desconocido que conduce a un resultado marginalmente mejor que el cálculo doble estándar de C / C ++.

GCC 4.5:

int main(int argc, char** argv) { long double a = 119106029; long double b = 1103515245; long double c = a * b; printf("%.Lf/n", c); return 0; }

Resultado:

131435318772912105

Esperado:

131435318772912105

Por lo tanto, no veo ninguna posibilidad en Javascript sin la ayuda de una biblioteca BIGNUM (si corresponde).

Saludos

rbo