Відповіді:
Ви робите 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, яка перевіряє, чи слід ви перекривати замість підлоги. Тож +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)
, використовуючи визначення та графіки з Вікіпедії :
За допомогою цих ділянок функції підлоги та стелі ви можете побачити взаємозв'язок.
Ви можете це бачити 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
на довгий)
поділ округляється вниз (до 4), перш ніж він перетворюється в подвійний (4.0), який потім округляється вгору (до 4.0)
якщо ви використовуєте змінні, ви можете цього уникнути
double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
Ніхто не згадав про найінтуїтивніше:
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;
результат - an 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
зробить це. Для цілих чисел це не дуже підштовхне їх до наступного цілого числа. На все інше воно буде.
Yikes. Сподіваємось, це має сенс. Я впевнений, що є більш математично вишуканий спосіб пояснити це.
Для перетворення числа з цілого числа в реальне число ви можете додати крапку:
int total = (int) Math.ceil(157/32.);
І результат (157/32.) Теж буде реальним. ;)
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);
}
}
int total = (157-1)/32 + 1
або більш загальне
(a-1)/b +1