ฟังก์ชัน Javascript ที่เขียนใหม่ใน Java ให้ผลลัพธ์ที่แตกต่าง


9

มีฟังก์ชัน Javascript ที่ฉันพยายามเขียนใน Java:

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

การปรับ Java ของฉัน:

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

เมื่อฉันผ่าน-1954896768รุ่น Javascript จะกลับ70528มาในขณะที่ Java กลับ-896768มา ฉันไม่แน่ใจว่าทำไม ความแตกต่างที่ดูเหมือนว่าจะเริ่มต้นภายในถ้าเงื่อนไข: ในฟังก์ชั่นจาวาสคริหลังจากที่ถ้าencodingRound2 = 2340070528ในขณะที่ใน encodingRound2 = -1954896768Java:

ฉันสร้างข้อความจำลองเหล่านี้เพื่อแสดงทางออนไลน์:

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

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

แก้ไข : การเปลี่ยนฟังก์ชั่น Java เป็นนี้

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

ดูเหมือนจะไม่ส่งผลต่อผลลัพธ์ แต่ก็ยัง -896768


1
ทำไมคุณencondindRound2ถึงเลือกที่จะintอยู่ในจาวาโค้ด? เนื่องจากมันถูกนิยามว่าเป็น a longคุณจะสูญเสียความแม่นยำหากคุณใช้แบบแคบ
— Jordan

1
@ Jordan เพราะ - ข้างใน if - มีการดำเนินการระดับบิตที่ดำเนินการอยู่ จาวาสคริปต์แม้ว่าการจัดเก็บตัวเลขเป็น 64- บิตลอยเมื่อทำ bitwise แปลงตัวเลขเป็นจำนวนเต็ม 32 บิต ฉันมีปัญหากับรหัสอื่นก่อนหน้านี้เมื่อทำ bitwise กับ Java ของlongให้ผลลัพธ์ที่แตกต่างเพราะล้น
— parsecer

การลบการ(int)ร่ายออกจากreturnบรรทัดไม่ได้เปลี่ยนผล Java มันยังคงอยู่-896768
— parsecer

4
ฉันพบปัญหาแล้ว เมื่อคุณตรึงบน... + 0x80000000Java จะแปลงค่าเป็น int เพราะ0x80000000ถือว่าเป็นตัวอักษรที่แท้จริง เปลี่ยนหมายเลข0x80000000Lนั้นเป็น
— จอร์แดน

1
@ จอร์แดนว้าวคุณเป็นตัวช่วยสร้าง! มันได้ผล! กรุณาโพสต์คำตอบของคุณและฉันจะยอมรับมัน
— parsecer

คำตอบ:


9

ใน Java 0x80000000 อยู่นอกช่วงของ 32 บิต int ดังนั้นมันจึงครอบคลุมถึง -2147483648

ใน JavaScript 0x80000000 นั้นอยู่ในช่วง 64 บิตเป็นสองเท่าดังนั้นจึงยังคงเป็น 2147483648

เห็นได้ชัดว่าการเพิ่ม-2147483648กับการเพิ่ม2147483648ผลในความแตกต่างที่มีขนาดใหญ่มาก

คุณสามารถใช้long0x80000000L ใน Java หรือบีบอัดหมายเลข JS ของคุณเป็น 32 บิตด้วย(0x80000000|0)ขึ้นอยู่กับที่คุณต้องการ


2

ลองสิ่งนี้ คุณต้องระบุค่ายาวในการทำการแปลง

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

        return  (encondindRound2 % 1_000_000);
    }

แต่มีปัญหาอื่นที่คุณควรระวัง Javascript ถือว่า%เป็นตัวดำเนินการโมดูโลโดยที่ Java ถือว่าเป็นตัวดำเนินการส่วนที่เหลืออย่างง่าย ลองอ่านโพสต์นี้ที่นี่สำหรับข้อมูลเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.