Разделение двух целых чисел и округление результата без использования с плавающей запятой

Мне нужно разделить два числа и округлить их. Есть ли лучший способ сделать это?

int myValue = (int) ceil( (float)myIntNumber / myOtherInt );

Я нахожу, что излишеству приходится бросать два разных времени. (extern int cast просто выключает предупреждение)

Примечание. Мне нужно отбрасывать внутренне, чтобы плавать в противном случае

int a = ceil(256/11); //> Should be 24, but it is 23
              ^example

Ответ 1

С помощью DyP появилась следующая нераспространенная формула:

int idiv_ceil ( int numerator, int denominator )
{
    return numerator / denominator
             + (((numerator < 0) ^ (denominator > 0)) && (numerator%denominator));
}

Он избегает конверсий с плавающей запятой и передает базовый набор модульных тестов, как показано ниже:


Здесь другая версия, которая позволяет избежать работы с модулем.

int idiv_ceil ( int numerator, int denominator )
{
    int truncated = numerator / denominator;
    return truncated + (((numerator < 0) ^ (denominator > 0)) &&
                                             (numerator - truncated*denominator));
}

Первый будет быстрее на процессорах, где IDIV возвращает как фактор, так и остаток (и компилятор достаточно умен, чтобы использовать это).

Ответ 2

Предполагая, что оба myIntNumber и myOtherInt положительны, вы можете сделать:

int myValue = (myIntNumber + myOtherInt - 1) / myOtherInt;

Ответ 3

Целочисленное деление с округлением.

Только 1 деление, выполненное за вызов, не % или * или преобразование в/из плавающей точки, работает для положительных и отрицательных int. См. Примечание (1).

n (numerator) = OPs myIntNumber;  
d (denominator) = OPs myOtherInt;

Следующий подход прост. int раунды деления на 0. Для отрицательных факторов это округление, поэтому ничего особенного не требуется. Для положительных коэффициентов добавьте d-1, чтобы выполнить округление, затем выполните беззнаковое деление.

Примечание (1) Обычное разделение на 0 разрывает ситуацию и MININT/-1 терпит неудачу, как ожидалось, на 2 комплиментных машинах.

int IntDivRoundUp(int n, int d) {
  // If n and d are the same sign ... 
  if ((n < 0) == (d < 0)) {
    // If n (and d) are negative ...
    if (n < 0) {
      n = -n;
      d = -d;
    }
    // Unsigned division rounds down.  Adding d-1 to n effects a round up.
    return (((unsigned) n) + ((unsigned) d) - 1)/((unsigned) d);  
  }
  else {
    return n/d;
  }
}

[Изменить: удаленный код проверки, см. предыдущий rev при необходимости]

Ответ 4

Просто используйте

int ceil_of_division = ((dividend-1)/divisor)+1;

Например:

for (int i=0;i<20;i++)
    std::cout << i << "/8 = " << ((i-1)/8)+1 << std::endl;

Ответ 5

Может быть, проще сделать a:

int result = dividend / divisor;
if(dividend % divisor != 0)
    result++;

Ответ 6

Небольшой взлом:

int divideUp(int a, int b) {
    result = (a-1)/b + 1;
}
// Proof:
a = b*N + k (always)
if k == 0, then
  (a-1)       == b*N  - 1
  (a-1)/b     == N - 1
  (a-1)/b + 1 == N ---> Good !

if k > 0, then
  (a-1)       == b*N   + l
  (a-1)/b     == N
  (a-1)/b + 1 == N+1  ---> Good !

Ответ 7

Вместо использования функции ceil перед литьем в int вы можете добавить константу, которая очень близка (но не совсем), равная 1 - таким образом, почти что угодно (кроме значения, которое точно или невероятно близко к фактическому целое число) будет увеличено на единицу до того, как оно будет усечено.

Пример:

#define EPSILON (0.9999)

int myValue = (int)(((float)myIntNumber)/myOtherInt + EPSILON);

EDIT: увидев ваш ответ на другой пост, я хочу уточнить, что это будет округлено, а не от нуля - отрицательные числа станут менее негативными, а положительные числа станут более положительными.