Есть ли какая-нибудь функция Java или класс util, который округляет таким образом: func (3/2) = 2?

Есть ли какая-нибудь функция Java или утилита class, которая округляет таким образом: func(3/2) = 2

Math.ceil() не помогает, что, по названию, должно было сделать. Я знаю BigDecimal, но мне это не нужно.


person Rig Veda    schedule 02.07.2009    source источник
comment
Вы хотите округлить только 0,5? или округление до 0,3 и т. д.?   -  person jvenema    schedule 02.07.2009
comment
@jvenema: Совершенно верно - большинство предлагаемых решений предполагают, что значение, превышающее 1.0, должно округляться до 2. Например, 7/3 равно 2.333, но округляется до 3. Однако, учитывая пример из OP, неясно, желательно ли это или нет.   -  person GalacticCowboy    schedule 02.07.2009
comment
Мне кажется, с тех пор, как он сначала попробовал ceil, это была именно та функциональность, которую он искал.   -  person jjnguy    schedule 02.07.2009
comment
да, это было то, что я искал. Просто я привел неправильные аргументы. Еще раз спасибо всем. :)   -  person Rig Veda    schedule 02.07.2009
comment
Непонятно, что нужно, но, по-видимому, дубликат этого более четкого вопроса: stackoverflow.com/questions/7446710/   -  person Raedwald    schedule 08.11.2013
comment
Возможный дубликат stackoverflow.com/questions/17944/   -  person Raedwald    schedule 08.11.2013
comment
@RigVeda: добавлено упрощение для случая деления на 2.   -  person Gil Vegliach    schedule 28.07.2017


Ответы (15)


Math.ceil() всегда будет округлять в большую сторону, однако вы делаете целочисленное деление с помощью 3/2. Таким образом, поскольку в целочисленном делении 3/2 = 1 (не 1.5) потолок 1 равен 1.

Для достижения желаемых результатов вам нужно Math.ceil(3/2.0);

Делая деление на двойную величину (2.0), вы в конечном итоге выполняете деление с плавающей запятой вместо целочисленного деления. Таким образом, 3/2.0 = 1.5, а ceil() из 1.5 всегда 2.

person jjnguy    schedule 02.07.2009

Немного черной магии, и все это можно проделать целыми числами:

// Divide x by n rounding up
int res = (x+n-1)/n
person Tal Pressman    schedule 02.07.2009
comment
На самом деле мне больше нравится этот метод, так как мне не нужно импортировать Math, приведение и т. Д. Спасибо! - person Mat; 21.05.2012
comment
@Mat С другой стороны, любому, кто читает ваш код, будет труднее понять, что вы делаете и почему. Это гораздо более веский аргумент против этого, чем любой из перечисленных вами аргументов. Однако вы можете извлечь его в метод с правильным именем, и тогда все в порядке. - person biziclop; 16.10.2012

Чтобы преобразовать разделение пола в разделение потолка:

(numerator + denominator-1) / denominator

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

(numerator + (denominator)/2) / denominator
person Randy Proctor    schedule 02.07.2009
comment
Первый также эквивалентен: ceil(n/d) = fl((n - 1)/d) + 1 - person Gil Vegliach; 09.01.2017

Вы всегда можете сыграть первыми:

Math.ceil((double)3/2)
person PatrikAkerstrand    schedule 02.07.2009

В Java 3/2 = 1, поскольку используется целочисленное деление. Нет функции, которая могла бы "исправить" это впоследствии. Что вам нужно сделать, так это вызвать деление с плавающей запятой и округлить результат:

int result = (int)Math.ceil( ((float)3) / ((float)2) );
person Michael Borgwardt    schedule 02.07.2009

Разве это не обычный случай целочисленного деления? Попробуйте Math.Ceil после преобразования любого числа в тип с плавающей запятой.

person sisve    schedule 02.07.2009
comment
3/2 уже возвращает только 1 (int), поэтому Math.ceil () ничего не делает. +1 - person AlbertoPL; 02.07.2009
comment
Целочисленное деление возвращает наибольшее число, которое делится поровну. Позволяя вам использовать модуль для получения остатка. - person Brian; 02.07.2009

Многие языки так «думают». Если вы делите int на int, вы должны получить int (поэтому они усекаются, и в результате вы получаете 1).

Все мы знаем, что это неправда, но они работают именно так. Вы можете «обмануть» их и сделать что-то вроде преобразования одного из них в двойное, или использовать двойное представление: Math.ceil (3.0 / 2) или Math.ceil((double)3/2), как упоминалось.

person Samuel Carrijo    schedule 02.07.2009

Math.ceil поможет, если вы используете числа с плавающей запятой. Проблема в том, что 3/2 при целочисленном делении равно 1. К тому времени, когда значение попадет в любую функцию, будь то Math.ceil или что-то еще, значение будет просто 1. Любая конечная десятичная часть исчезнет.

person Pesto    schedule 02.07.2009

if (a % b == 0)
{
  return (a / b);
}
else
{
  return (a / b) + 1;
}

Использует целочисленное деление, чтобы делать то, что вы хотите. Я не знаю математической функции, которая бы это сделала, но почему бы не свернуть свою собственную?

person Brian    schedule 02.07.2009

приведенный ниже фрагмент также работает с отрицательными целыми числами:

public static int divRoundUp(int x, int n) {
    if (n<=0) throw new RuntimeException("conceived wt. pos. dividers (was:"+n+")");
    int ret = (x+(n-1)*(x>0?1:0))/n;
    return ret;
}
person Marcus Junius Brutus    schedule 13.01.2011

Если вы хотите просто разделить на 2, вы можете:

n - n / 2

И вообще:

(n - 1) / d + 1 == (n + d - 1) / d

Это верно для неотрицательных целых чисел. Как расширить его до отрицательных целых чисел, зависит от того, что вы имеете в виду под «округлением таким образом». Целочисленное деление округляется до нуля, тогда как Math.ceil() округляет в большую сторону, а Math.floor() - в меньшую. Например, n / 2 != (int) Math.floor(n / 2.0) для n == -5.

Если вы хотите всегда округлять, вы можете использовать Math.ceil(), как в этом ответе.

person Gil Vegliach    schedule 28.07.2017
comment
Просто и избавит вас от необходимости превращаться в двойника. Мне это нравится. - person Anirudh; 17.02.2020

Если вы действительно хотите избежать использования ceil и литья, вот небольшой метод, который выполняет то же самое.

public int findCeil(int X, int Y) {
        if (X % Y == 0){
            return X / Y;
        } else {
            return X / Y + 1;
        }
    }
person Timothy Osborn    schedule 13.07.2018

Мне больше всего нравится ответ Рэнди Проктора. Здесь поподробнее:

Если вы хотите выполнить реальное округление (т.е. 3/2 -> 2, но 17/7 -> 2) с целыми числами> 0: используйте (dividend + (divisor / 2)) / divisor вместо dividend / divisor.

Если дивиденд может быть любым целым числом (т.е. допускается отрицательное значение): (dividend >= 0) ? ((dividend + divisor / 2) / divisor) : ((dividend - divisor / 2) / divisor).

Если дивиденд - любое целое число, а делитель - любое целое число, кроме 0: (dividend >= 0) ? ((dividend + Math.abs(divisor) / 2) / divisor) : ((dividend - Math.abs(divisor) / 2) / divisor).

(Обратите внимание, что сложение и вычитание могут вызвать зацикливание, которое в противном случае не произошло бы, что приведет к неверному результату.)

person DaveFar    schedule 27.07.2011

Вот метод, который я создал для обработки деления int без использования Math Round и приведения к float. Это работает для положительных и отрицательных чисел. Он работает, добавляя половину знаменателя, чтобы компенсировать округление в меньшую сторону.

public static int div_Int(int num, int den){
    if(num > 0 && den > 0 || num < 0 && den < 0 ){
        return ((2*num)+ den)/(2*den);  
    }else{
        return ((2*num)- den)/(2*den);
    }

}
person pt123    schedule 13.05.2013

Вы пробовали Math.floor()?

person Tony Miller    schedule 02.07.2009
comment
Это поведение, противоположное тому, что он хочет. - person Brian; 02.07.2009