Fungsi Javascript yang ditulis ulang di Jawa memberikan hasil yang berbeda


9

Ada fungsi Javascript yang saya coba tulis ulang di Java:

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

Adaptasi Java saya:

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

Ketika saya lulus -1954896768, versi Javascript kembali 70528, sedangkan Java kembali -896768. Saya tidak yakin mengapa. Perbedaannya tampaknya mulai dalam kondisi jika: dalam fungsi Javascript setelah jika encodingRound2 = 2340070528, sementara di Jawa: encodingRound2 = -1954896768.

Saya membuat balasan ini untuk ditampilkan secara online:

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

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

EDIT : Mengubah fungsi Java untuk ini

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

tampaknya tidak mempengaruhi hasilnya - masih -896768


1
Mengapa Anda melakukan casting encondindRound2ke intdalam kode Java? Karena itu didefinisikan sebagai long, Anda akan berpotensi kehilangan presisi jika Anda melemparkannya ke tipe yang lebih sempit.
Jordan

1
@ Jordan karena - di dalam if - ada operasi bitwise yang dilakukan di atasnya. Javascript, meskipun menyimpan angka sebagai pelampung 64-bit, saat melakukan bitwise, mengubah angka menjadi bilangan bulat 32-bit. Saya memiliki masalah ini dengan potongan kode lain sebelumnya, ketika melakukan bitwise dengan Java longmemberikan hasil yang berbeda, karena overflow.
parsecer

Menghapus (int)gips dari returngaris tidak mengubah hasil Java, tetap-896768
parsecer

4
Ah, saya menemukan masalahnya. Ketika Anda melakukan tack ... + 0x80000000, Java mengkonversi nilai menjadi int, karena 0x80000000dianggap sebagai int literal. Ubah nomor itu menjadi 0x80000000L.
Jordan

1
@ Jordan Wow, kau penyihir! Berhasil! Silakan kirim jawaban Anda dan saya akan menerimanya
parsecer

Jawaban:


9

Di Jawa, 0x80000000 berada di luar kisaran int 32bit, sehingga membungkus ke -2147483648.

Dalam JavaScript, 0x80000000 berada dalam kisaran 64bit ganda, sehingga tetap 2147483648.

Jelas, menambahkan -2147483648vs menambahkan 2147483648hasil dalam perbedaan yang sangat besar.

Anda bisa menggunakan long0x80000000L di Java, atau memaksa nomor JS Anda ke int 32bit (0x80000000|0), tergantung yang Anda inginkan.


2

Coba ini. Anda perlu menentukan nilai panjang dalam melakukan konversi.

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

        return  (encondindRound2 % 1_000_000);
    }

Tetapi ada masalah lain yang harus Anda waspadai. Javascript memperlakukan %sebagai operator modulo di mana Java memperlakukannya sebagai operator sisa sederhana. Lihat posting ini di sini untuk informasi lebih lanjut.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.