Java округляется до int с использованием Math.ceil - PullRequest
86 голосов
/ 21 августа 2011
int total = (int) Math.ceil(157/32);

Почему он по-прежнему возвращает 4?157/32 = 4.90625, мне нужно округлить, я посмотрел вокруг, и это, кажется, правильный метод.

Я пробовал total как double тип, но получаю 4.0.

Что я делаю не так?

Ответы [ 14 ]

159 голосов
/ 17 февраля 2014

Вы делаете 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, который проверяет, стоит ли вам использовать ceil вместо пола.Так что +1 или +0, если есть остаток с делением, вам нужно +1.a % b == 0 проверяет остаток.

Вариант 2

Этот параметр очень короткий, но, возможно, для некоторых менее интуитивно понятен.Я думаю, что этот менее интуитивный подход будет быстрее, чем подход двойного деления и сравнения:

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 : enter image description here

С помощью этих графиков функции пола и потолка вы можете увидеть отношения.

Floor function Ceil function

Вы можете видеть это 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 .

59 голосов
/ 21 августа 2011

157/32 равно int/int, что приводит к int.

Попробуйте использовать двойной литерал - 157/32d, то есть int/double, что приводит к double.

34 голосов
/ 21 августа 2011

157/32 является целочисленным делением, поскольку все числовые литералы являются целыми числами, если иное не указано с суффиксом (d для двойного l для длинного)

деление округляется в меньшую сторону (до 4), а затем преобразуется в двойное (4,0), которое затем округляется в большую сторону (до 4,0)

если вы используете переменные, вы можете избежать этого

double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
24 голосов
/ 21 марта 2013
int total = (int) Math.ceil((double)157/32);
3 голосов
/ 13 июня 2015

При делении двух целых чисел, например,

int c = (int) a / (int) b;

результат - int, значение которого a, деленное на b, округленное до нуля. Поскольку результат уже округлен, ceil() ничего не делает. Обратите внимание, что это округление отличается от floor(), которое округляется в сторону отрицательной бесконечности. Итак, 3/2 равно 1floor(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 сделает это. Для целых чисел это не совсем подтолкнет их к следующему целому числу. Для всего остального, это будет.

Хлоп. Надеюсь, это имеет смысл. Я уверен, что есть более математически элегантный способ объяснить это.

3 голосов
/ 26 июня 2014

В Java добавление .0 сделает его двойным ...

int total = (int) Math.ceil(157.0 / 32.0);
2 голосов
/ 30 января 2014
int total = (int) Math.ceil( (double)157/ (double) 32);
1 голос
/ 23 января 2018

Есть два метода, с помощью которых вы можете округлить свое двойное значение.

  1. Math.ceil
  2. Math.floor

Если вы хотите, чтобы ваш ответ 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);

    }

}
1 голос
/ 30 августа 2017

Никто не упомянул самое интуитивное:

int x = (int) Math.round(Math.ceil((double) 157 / 32));

Это решение устраняет неточность деления double .

1 голос
/ 02 июля 2015

Проверьте решение ниже для вашего вопроса:

int total = (int) Math.ceil(157/32);

Здесь вы должны умножить числитель на 1,0, тогда он даст ваш ответ.

int total = (int) Math.ceil(157*1.0/32);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...