int total = (int) Math.ceil(157/32);
ทำไมมันยังกลับ 4? 157/32 = 4.90625, ฉันต้องสรุป, ฉันมองไปรอบ ๆ และดูเหมือนจะเป็นวิธีการที่ถูกต้อง
ฉันพยายามtotalเป็นdoubleประเภท แต่ได้รับ 4.0
ผมทำอะไรผิดหรือเปล่า?
int total = (int) Math.ceil(157/32);
ทำไมมันยังกลับ 4? 157/32 = 4.90625, ฉันต้องสรุป, ฉันมองไปรอบ ๆ และดูเหมือนจะเป็นวิธีการที่ถูกต้อง
ฉันพยายามtotalเป็นdoubleประเภท แต่ได้รับ 4.0
ผมทำอะไรผิดหรือเปล่า?
คำตอบ:
คุณกำลังทำ157/32ซึ่งกำลังหารจำนวนเต็มสองจำนวนด้วยกันซึ่งจะส่งผลให้จำนวนเต็มปัดลงเสมอ ดังนั้นจึง(int) Math.ceil(...)ไม่ได้ทำอะไร มีสามวิธีที่เป็นไปได้เพื่อให้บรรลุสิ่งที่คุณต้องการ ผมขอแนะนำให้ใช้ตัวเลือก 1หรือ2 ตัวเลือก กรุณาอย่าไม่ใช้ตัวเลือก 0
## ตัวเลือก 0
แปลงaและbเป็นสองเท่าและคุณสามารถใช้การหารและMath.ceilตามที่คุณต้องการให้ทำงานได้ อย่างไรก็ตามฉันไม่แนะนำอย่างยิ่งที่จะใช้แนวทางนี้เนื่องจากการหารสองอาจไม่ชัดเจน หากต้องการอ่านเพิ่มเติมเกี่ยวกับความไม่แม่นยำของคู่ผสมโปรดดูคำถามนี้
int n = (int) Math.ceil((double) a / b));
##ตัวเลือกที่ 1
int n = a / b + ((a % b == 0) ? 0 : 1);
คุณทำa / bพื้นเสมอถ้าaและbเป็นจำนวนเต็มทั้งคู่ จากนั้นคุณจะมี if-statement Witch แบบอินไลน์ตรวจสอบว่าคุณควรหยุดแทนพื้นหรือไม่ ดังนั้น +1 หรือ +0 หากมีส่วนที่เหลืออยู่ในส่วนที่คุณต้องการ +1 a % b == 0ตรวจสอบส่วนที่เหลือ
## ทางเลือกที่ 2
ตัวเลือกนี้สั้นมาก แต่อาจใช้งานง่ายสำหรับบางคน ผมคิดว่าวิธีการที่ใช้งานง่ายน้อยนี้จะเร็วกว่าคู่ส่วนและการเปรียบเทียบวิธีการ: หมายเหตุโปรดที่ว่านี้ไม่ได้ทำงาน
b < 0
int n = (a + b - 1) / b;
เพื่อลดโอกาสการล้นคุณสามารถใช้สิ่งต่อไปนี้ อย่างไรก็ตามโปรดทราบว่ามันไม่ได้ทำงานให้และa = 0b < 1
int n = (a - 1) / b + 1;
## คำอธิบายเบื้องหลัง "แนวทางที่ใช้งานง่ายน้อย"
เนื่องจากการหารจำนวนเต็มสองจำนวนใน Java (และภาษาโปรแกรมอื่น ๆ ส่วนใหญ่) จะปูพื้นผลลัพธ์เสมอ ดังนั้น:
int a, b;
int result = a/b (is the same as floor(a/b) )
แต่เราไม่ต้องการfloor(a/b)แต่ceil(a/b)ใช้คำจำกัดความและแผนการจากWikipedia :
ด้วยพล็อตของฟังก์ชันพื้นและเพดานเหล่านี้คุณจะเห็นความสัมพันธ์

floor(x) <= ceil(x)คุณจะเห็นว่า floor(x + s) = ceil(x)เราจำเป็นต้อง sดังนั้นเราจึงต้องไปหา ถ้าเราใช้1/2 <= s < 1มันจะถูกต้อง (ลองใช้ตัวเลขแล้วคุณจะเห็นว่าเป็นเช่นนั้นฉันพบว่าตัวเองยากที่จะพิสูจน์สิ่งนี้) และ1/2 <= (b-1) / b < 1ดังนั้น
ceil(a/b) = floor(a/b + s)
= floor(a/b + (b-1)/b)
= floor( (a+b-1)/b) )
นี่ไม่ใช่ข้อพิสูจน์ที่แท้จริง แต่ฉันหวังว่าคุณจะพอใจกับมัน หากมีใครสามารถอธิบายได้ดีกว่านี้ฉันก็จะขอบคุณเช่นกัน อาจจะถามมันในMathOverflow
157/32 คือint/intซึ่งส่งผลให้เกิดintไฟล์.
ลองใช้ตัวอักษรคู่ - 157/32dซึ่งเป็นซึ่งจะส่งผลให้int/doubledouble
157/32คือการหารจำนวนเต็มเนื่องจากตัวอักษรตัวเลขทั้งหมดเป็นจำนวนเต็มเว้นแต่จะระบุไว้เป็นอย่างอื่นด้วยคำต่อท้าย ( dสำหรับคู่lสำหรับ long)
การแบ่งจะถูกปัดเศษลง (เป็น 4) ก่อนที่จะถูกแปลงเป็นสองเท่า (4.0) ซึ่งจะถูกปัดเศษขึ้น (เป็น 4.0)
หากคุณใช้ตัวแปรคุณสามารถหลีกเลี่ยงสิ่งนั้นได้
double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
int total = (int) Math.ceil((double)157/32);
ไม่มีใครพูดถึงสิ่งที่เข้าใจง่ายที่สุด:
int x = (int) Math.round(Math.ceil((double) 157 / 32));
โซลูชันนี้แก้ไขความไม่แม่นยำของการหารสอง
ใน Java การเพิ่ม. 0 จะทำให้เป็นสองเท่า ...
int total = (int) Math.ceil(157.0 / 32.0);
เมื่อหารจำนวนเต็มสองจำนวนเช่น
int c = (int) a / (int) b;
ผลลัพธ์คือintค่าที่aหารด้วยbปัดเศษเข้าหาศูนย์ เพราะปัดแล้วผลceil()ไม่ได้ทำอะไร โปรดทราบว่าการปัดเศษนี้ไม่เหมือนกับการfloor()ปัดเศษของค่าอินฟินิตี้เชิงลบ ดังนั้น3/2เท่ากับ1(และfloor(1.5)เท่ากับ1.0แต่(-3)/2เท่ากับ-1(แต่floor(-1.5)เท่ากับ-2.0)
นี้เป็นสิ่งสำคัญเพราะถ้าa/bได้เสมอเช่นเดียวfloor(a / (double) b)แล้วคุณก็สามารถใช้ceil()ในการเป็นa/b-( (-a) / b)
ข้อเสนอแนะในการเดินทางceil(a/b)จาก
int n = (a + b - 1) / b;ซึ่งเทียบเท่ากับa / b + (b - 1) / bหรือ(a - 1) / b + 1
ใช้ได้ผลเพราะceil(a/b)มากกว่าหนึ่งเสมอfloor(a/b)ยกเว้นเมื่อa/bเป็นจำนวนเต็ม ดังนั้นคุณต้องการชนกับ (หรืออดีต) จำนวนเต็มถัดไปเว้นแต่a/bเป็นจำนวนเต็ม การเพิ่ม1 - 1 / bจะดำเนินการนี้ สำหรับจำนวนเต็มมันจะไม่ดันขึ้นไปที่จำนวนเต็มถัดไป สำหรับทุกสิ่งทุกอย่างก็จะ
อือ. หวังว่าจะสมเหตุสมผล ฉันแน่ใจว่ามีวิธีอธิบายที่สง่างามทางคณิตศาสตร์มากกว่านี้
นอกจากนี้ในการแปลงตัวเลขจากจำนวนเต็มเป็นจำนวนจริงคุณสามารถเพิ่มจุด:
int total = (int) Math.ceil(157/32.);
และผลลัพธ์ของ (157/32.) ก็จะเป็นจริงเช่นกัน ;)
int total = (int) Math.ceil( (double)157/ (double) 32);
ตรวจสอบคำตอบด้านล่างสำหรับคำถามของคุณ:
int total = (int) Math.ceil(157/32);
ที่นี่คุณควรคูณ Numerator ด้วย 1.0 จากนั้นจะให้คำตอบของคุณ
int total = (int) Math.ceil(157*1.0/32);
ใช้สองครั้งในการหล่อ
Math.ceil((double)value) หรือชอบ
Math.ceil((double)value1/(double)value2);
Java จัดเตรียมเฉพาะการแบ่งชั้น/ตามค่าเริ่มต้น แต่เราสามารถเขียนเพดานในแง่ของชั้น มาดูกัน:
จำนวนเต็มใด ๆสามารถเขียนแบบที่y y == q*k+rตามคำนิยามของการแบ่งชั้น (ที่นี่floor) ซึ่งรอบนอกr,
floor(q*k+r, k) == q , where 0 ≤ r ≤ k-1
และในส่วนของเพดาน (ที่นี่ceil) ซึ่งรอบขึ้นr₁,
ceil(q*k+r₁, k) == q+1 , where 1 ≤ r₁ ≤ k
ที่เราสามารถใช้แทนr+1สำหรับr₁:
ceil(q*k+r+1, k) == q+1 , where 0 ≤ r ≤ k-1
จากนั้นเราแทนที่สมการแรกเป็นสมการที่สามเพื่อqรับ
ceil(q*k+r+1, k) == floor(q*k+r, k) + 1 , where 0 ≤ r ≤ k-1
ในที่สุดได้รับจำนวนเต็มใด ๆyที่y = q*k+r+1บางq, k, rเรามี
ceil(y, k) == floor(y-1, k) + 1
และเราทำเสร็จแล้ว หวังว่านี่จะช่วยได้
ceilนิยามเช่นนี้จากคำจำกัดความที่เข้าใจง่ายโดยเฉพาะอย่างยิ่งเมื่อเรานำค่าเพดานของจำนวนเต็มคือ r1 = k เนื่องจากกรณีขอบเป็นสิ่งที่ยุ่งยากเกี่ยวกับเรื่องนี้ฉันคิดว่ามันต้องสะกดให้มากขึ้น
มีสองวิธีที่คุณสามารถปัดเศษค่าสองเท่าได้
หากคุณต้องการคำตอบของคุณ 4.90625 เป็น 4 คุณควรใช้ Math.floor และหากคุณต้องการคำตอบของคุณ 4.90625 เป็น 5 คุณสามารถใช้ Math.ceil
คุณสามารถอ้างอิงรหัสต่อไปนี้ได้
public class TestClass {
public static void main(String[] args) {
int floorValue = (int) Math.floor((double)157 / 32);
int ceilValue = (int) Math.ceil((double)157 / 32);
System.out.println("Floor: "+floorValue);
System.out.println("Ceil: "+ceilValue);
}
}
ฉันรู้ว่านี่เป็นคำถามเก่า แต่ในความคิดของฉันเรามีแนวทางที่ดีกว่าซึ่งใช้BigDecimalเพื่อหลีกเลี่ยงการสูญเสียความแม่นยำ อย่างไรก็ตามการใช้โซลูชันนี้เรามีความเป็นไปได้ที่จะใช้กลยุทธ์การปัดเศษและการปรับขนาดต่างๆ
final var dividend = BigDecimal.valueOf(157);
final var divisor = BigDecimal.valueOf(32);
final var result = dividend.divide(divisor, RoundingMode.CEILING).intValue();
int total = (157-1)/32 + 1
หรือทั่วไปมากขึ้น
(a-1)/b +1