Pregunta

Java and Javascript produces different result when operating with large integers.

Example: getCode(1747,1763,-268087281,348400) returns 1921968083 in Java but Javascript returns 2.510115715670451e+22.

How do I get the result in Java using Javascript?

Having done some research the problem seems to be related to signed/unsigned 32/64 bit integer operations. I have tried adding |0 to the and of all operations and got 1921618368 which is closer but not identical.

Java:

public String getCode(int intVal1, int intVal2, int intVal3, int IntA) {
    int intVal5 = intVal2 ^ intVal3  ;
    intVal5 = intVal5 + (intVal1 | IntA )  ;
    intVal5 = intVal5 * (intVal1 | intVal3  ) ;
    intVal5 = intVal5 * (intVal2 ^ IntA )  ;
    return String.valueOf(intVal5);
}

Javascript:

function getCode(intVal1,intVal2,intVal3,IntA)  {
    var intVal5 = intVal2 ^ intVal3  ;
    intVal5 = intVal5 + (intVal1 | IntA )  ;
    intVal5 = intVal5 * (intVal1 | intVal3  ) ;
    intVal5 = intVal5 * (intVal2 ^ IntA )  ;
    return intVal5;
}
¿Fue útil?

Solución

The |0 trick works well for most operations in JavaScript to simulate 32-bit ints, but not for multiplication. This is because multiplying two large ints can result in a number so big that it exceeds the integer precision of JavaScript's native double type. Once that is cast back to an int, the value is slightly wrong.

To deal with this, Math.imul was introduced to perform true int multiplication. It's very new, so browser support naturally excludes IE. Good news though: the linked page contains a replacement function that simulates imul for older browsers, which works by multiplying the top and bottom halves of the numbers separately.

Here is how to fix your function. It uses |0 after addition, and Math.imul for multiplication:

function getCode(intVal1, intVal2, intVal3, IntA) {
    var intVal5 = intVal2 ^ intVal3;
    intVal5 = intVal5 + (intVal1 | IntA) | 0;
    intVal5 = Math.imul(intVal5, (intVal1 | intVal3));
    intVal5 = Math.imul(intVal5, (intVal2 ^ IntA));
    return intVal5;
}
alert(getCode(1747, 1763, -268087281, 348400));

The output is 1921968083, identical to Java.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top