เหตุใด Math.floor จึงคืนค่าสองเท่า


104

Javadoc อย่างเป็นทางการบอกว่าMath.floor()ส่งคืนค่าdoubleที่ "เท่ากับจำนวนเต็มทางคณิตศาสตร์" แต่ทำไมไม่ส่งกลับint?

คำตอบ:


80

ตาม Javadoc เดียวกัน:

ถ้าอาร์กิวเมนต์เป็นNaNหรือเป็นอินฟินิตี้หรือศูนย์บวกหรือศูนย์ลบผลลัพธ์จะเหมือนกับอาร์กิวเมนต์ ไม่สามารถทำได้ด้วยintไฟล์.

ที่ใหญ่ที่สุดdoubleคุ้มค่านอกจากนี้ยังมีขนาดใหญ่กว่าที่ใหญ่ที่สุดดังนั้นมันจะต้องเป็นintlong


41
ดูเหมือนจะไม่สอดคล้องกับฟังก์ชัน Math.Round ซึ่งจะส่งกลับ int / long และจัดการกรณีพิเศษในลักษณะที่ต่างออกไป
zod

1
ขอให้สังเกต Javadoc กล่าวว่ามันจะกลับ"ที่ใหญ่ที่สุด (ใกล้เคียงกับอินฟินิตี้บวก) * ค่าจุดลอยตัว *ที่น้อยกว่าหรือเท่ากับการโต้แย้งและจะมีค่าเท่ากับจำนวนเต็มคณิตศาสตร์" กำหนดค่าx> 2 ^ 53ซึ่งจะไม่เหมือนกับค่าที่มีการตัดทอนส่วนเศษส่วน มันอาจจะค่อนข้างเล็กกว่านั้น
Jim Garrison

16

เพื่อความแม่นยำ ประเภทข้อมูลคู่มีแมนทิสซา 53 บิต เหนือสิ่งอื่นใดนั่นหมายความว่าคู่สามารถแทนค่าทั้งหมดได้ถึง 2 ^ 53 โดยไม่มีการสูญเสียความแม่นยำ

หากคุณจัดเก็บจำนวนมากเป็นจำนวนเต็มคุณจะได้รับจำนวนมากเกินไป จำนวนเต็มมีเพียง 32 บิต

การส่งคืนจำนวนเต็มเป็นสองเท่าเป็นสิ่งที่ถูกต้องที่จะทำที่นี่เพราะมีช่วงจำนวนที่มีประโยชน์ที่กว้างกว่าจำนวนเต็ม


แน่นอนว่ามันอาจกลับมายาวนานเพื่อรับมือกับค่านิยมดังกล่าว คุณยังคงต้องหาว่าจะทำอย่างไรกับ doubles> 2 ^ 63
Jon Skeet

1
@ จอนจริง แต่นั่นจะส่งผลต่อประสิทธิภาพ (ไม่มีคำแนะนำการแปลงจาก long ไปเป็นสองเท่าในชุดคำสั่งใด ๆ ที่ฉันรู้) ฉันสงสัยว่า Math.floor ทำอะไรกับ doubles> 2 ^ 53 ในตอนแรก ผลลัพธ์บางอย่างไม่สามารถแสดงได้
Nils Pipenbrinck

แต่แล้วรูปแบบ pseudo-idiomatic (int) Math.floor (foo) ซึ่งปรากฏใน javadoc อย่างเป็นทางการนั้นไม่ปลอดภัยเนื่องจากผลลัพธ์อาจไม่พอดีกับ int ฉันถูกไหม จากนั้นอีกครั้งซึ่งเป็นรูปแบบที่ปลอดภัยในการใช้ Math.floor เนื่องจากผลลัพธ์อาจไม่พอดีกับความยาว?
Raibaz

10

คนอื่นบอกคุณว่าทำไมฉันจะบอกวิธีการปัดเศษอย่างถูกต้องเนื่องจากคุณต้องการทำสิ่งนี้ หากคุณจะใช้ตัวเลขบวกเท่านั้นคุณสามารถใช้คำสั่งนี้:

int a=(int) 1.5;

อย่างไรก็ตาม (int) จะปัดเศษเข้าหา 0 เสมอดังนั้นหากคุณต้องการหาจำนวนลบ:

int a=(int) -1.5; //Equal to -1

ในกรณีของฉันฉันไม่ต้องการทำสิ่งนี้ ฉันใช้รหัสต่อไปนี้เพื่อทำการปัดเศษและดูเหมือนว่าจะจัดการกับขอบทั้งหมดได้ดี:

private static long floor(double a)
{
    return (int) Math.floor(a);
}

7
ทำไมไม่ใช้(int) Math.floor(a)? อาจมีประสิทธิภาพมากกว่าและสั้นกว่า
Solomon Ucko

@Solomon Ucko แทนคุณ(int) Math.floor(a)สามารถเขียน(int) aได้ถ้า a เป็นบวก
Leo Leontev

3

คุณต้องการให้มันส่งคืนอะไรถ้าคุณให้มันเป็นสองเท่าที่ใหญ่กว่า int หรือ long ที่ใหญ่ที่สุด?

(เป็นที่ยอมรับถ้ามันใหญ่กว่าความยาวที่ใหญ่ที่สุดความแม่นยำก็จะต่ำอยู่ดี - มันอาจไม่ใช่จำนวนเต็มทางทฤษฎีที่ใกล้ที่สุด - แต่ถึงอย่างนั้น ... )


0

เช่นเดียวกับที่มีจำนวนเต็มและการหารทศนิยมใน Java จึงมีวิธีการทำพื้นจำนวนเต็มและทศนิยม:

double f = Math.floor(x);

หรือ

int k = (int) x; 

แต่คุณต้องระมัดระวังในการใช้พื้นด้วยเลขคณิตที่มีความแม่นยำ จำกัด เสมอ: การคำนวณ x ของคุณอาจให้ผลตอบแทนเช่น 1.99999999 ซึ่งจะปูพื้นเป็น 1 ไม่ใช่ 2 ทั้งสองรูปแบบ มีอัลกอริทึมมากมายที่จำเป็นต้องหลีกเลี่ยงข้อ จำกัด นี้เพื่อหลีกเลี่ยงการสร้างผลลัพธ์ที่ไม่ถูกต้องสำหรับค่าอินพุตบางค่า


0

เพื่อให้ข้อผิดพลาดและค่าอื่น ๆ ที่ไม่ใช่จำนวนเต็มสามารถเรียงซ้อนผ่านชุดการคำนวณได้อย่างถูกต้อง

ตัวอย่างเช่นหากคุณป้อน Not a Number (NaN) ลงใน Math.floor ก็จะส่งต่อไป

หากส่งคืนจำนวนเต็มก็จะไม่สามารถส่งผ่านสถานะหรือข้อผิดพลาดเหล่านี้ไปได้และคุณอาจได้รับผลลัพธ์ที่ไม่ดีจากการคำนวณก่อนหน้านี้ที่ดูดี แต่ผิดหลังจากการประมวลผลเพิ่มเติม

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