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 = 0
b < 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/double
double
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