Die in Java neu geschriebene Javascript-Funktion liefert unterschiedliche Ergebnisse

9

Es gibt diese Javascript-Funktion, die ich in Java neu schreiben möchte:

function normalizeHash(encondindRound2) {
    if (encondindRound2 < 0) {
        encondindRound2 = (encondindRound2 & 0x7fffffff) + 0x80000000;
    }
    return encondindRound2 % 1E6;
}

Meine Java-Anpassung:

public long normalizeHash(long encondindRound2) {
        if (encondindRound2 < 0) {
            encondindRound2 = (((int) encondindRound2) & 0x7fffffff) + 0x80000000;
        }
        return (((int) encondindRound2) % 1_000_000);
    }

Wenn ich bestanden habe -1954896768, kehrt die Javascript-Version zurück 70528, während Java zurückkehrt -896768. Ich bin mir nicht sicher warum. Der Unterschied scheint innerhalb der if-Bedingung zu beginnen: in der Javascript-Funktion nach dem ifencodingRound2 = 2340070528 , während in Java : encodingRound2 = -1954896768.

Ich habe diese Antworten gemacht, um es online zu zeigen:

Javascript : https://repl.it/repls/NumbGuiltyHack

Java : https://repl.it/repls/ClumsyQualifiedProblem

BEARBEITEN : Ändern der Java-Funktion in diese

public long normalizeHash(long encondindRound2) {
        if (encondindRound2 < 0) {
            encondindRound2 = (encondindRound2 & 0x7fffffff) + 0x80000000;
        }
        return (encondindRound2 % 1_000_000);
    }

scheint das Ergebnis nicht zu beeinflussen - es ist immer noch -896768

Parsecer
quelle
1
Warum gießen Sie encondindRound2in einen intim Java-Code? Da es als definiert ist long, verlieren Sie möglicherweise an Präzision, wenn Sie es auf einen engeren Typ umwandeln.
Jordanien
1
@ Jordan, weil - innerhalb des if - eine bitweise Operation ausgeführt wird. Obwohl Javascript Zahlen als 64-Bit-Floats speichert, konvertiert es bei bitweiser Ausführung Zahlen in 32-Bit-Ganzzahlen. Ich hatte dieses Problem mit einem anderen Code zuvor, als ich bitweise mit Java arbeitete long, was aufgrund des Überlaufs zu unterschiedlichen Ergebnissen führte.
Parsecer
Das Entfernen der (int)Besetzung aus der returnZeile ändert nichts am Java-Ergebnis, es bleibt-896768
Parsecer
4
Ah, ich habe das Problem gefunden. Wenn Sie fortfahren ... + 0x80000000, konvertiert Java den Wert in ein int, da 0x80000000dies als int-Literal betrachtet wird. Ändern Sie diese Nummer in 0x80000000L.
Jordanien
1
@ Jordan Wow, du bist ein Zauberer! Es funktionierte! Bitte
poste

Antworten:

9

In Java liegt 0x80000000 außerhalb des Bereichs eines 32-Bit-Int, sodass es sich um -2147483648 handelt.

In JavaScript liegt 0x80000000 deutlich im Bereich eines 64-Bit-Double, sodass es 2147483648 bleibt.

Offensichtlich führt das Hinzufügen -2147483648gegenüber dem Hinzufügen 2147483648zu einer sehr großen Diskrepanz.

Sie können entweder eine long0x80000000L in Java verwenden oder Ihre JS-Nummer in eine 32-Bit-Int mit zwingen (0x80000000|0), je nachdem, was Sie möchten.

dieser andere Typ
quelle
2

Versuche dies. Bei der Konvertierung müssen Sie lange Werte angeben.

    public static long normalizeHash(long encondindRound2) {
        if (encondindRound2 < 0) {
            encondindRound2 =  (encondindRound2 & 0x7fffffffL) + 0x80000000L;
        }

        return  (encondindRound2 % 1_000_000);
    }

Es gibt jedoch noch ein anderes Problem, dessen Sie sich bewusst sein sollten. Javascript wird %als Modulo-Operator behandelt, Java als einfacher Restoperator. Weitere Informationen finden Sie in diesem Beitrag hier .

WJS
quelle