2009-07-02 2 views
16

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

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

+0

Спасибо каждому, –

+3

Вы ищете только округление 0,5 до? или округление 0,3 и т. д.? – jvenema

+0

@jvenema: Точно - большинство предлагаемых решений предполагают, что что-либо более 1.0 должно округлить до 2. Например, 7/3 равно 2.333, но будет округлено до 3. Однако, учитывая пример из OP, неясно, желаемо ли это или нет. – GalacticCowboy

ответ

50

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.

4

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

+1

3/2 уже возвращает 1 (int), поэтому Math.ceil() ничего не делает.+1 – AlbertoPL

+0

Целочисленное деление возвращает наибольшее число, которое равномерно делит. Позволяя вам использовать модуль, чтобы получить остаток. – Brian

2

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

38

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

// Divide x by n rounding up 
int res = (x+n-1)/n 
+11

Предполагая, что x положителен! – Niki

+0

Мне действительно нравится этот метод больше, так как мне не нужно импортировать Math, литье и т. Д. И т. Д. Спасибо! – Mat

+2

@Mat С другой стороны, любому, кто читает ваш код, будет сложнее выяснить, что вы делаете и почему. Это гораздо более сильный аргумент против этого, чем любой из тех, которые вы указали для него. Однако вы можете извлечь его в правильно названный метод, и тогда все в порядке. – biziclop

-2

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

+2

Это противоположное поведение того, что он хочет. – Brian

5

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

int result = (int)Math.ceil(((float)3)/((float)2)); 
3

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

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

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

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

+0

«Почему бы вам не катиться?» Из-за читаемости кода. – NeplatnyUdaj

9

Для преобразования пола деления до потолка деления:

(numerator + denominator-1)/denominator 

Для преобразования пола подразделения округляющего деления:

(numerator + (denominator)/2)/denominator 
+0

Первый также эквивалентен: 'ceil (n/d) = fl ((n - 1)/d) + 1' –

1

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

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; 
} 
0

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

Если вы хотите сделать реальное округление (т.е. 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).

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

0

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

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); 
    } 

} 
0

Если вы хотите просто разделить на 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(), как в this answer.