Разделение двух целых чисел и округление результата без использования с плавающей запятой
Мне нужно разделить два числа и округлить их. Есть ли лучший способ сделать это?
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: увидев ваш ответ на другой пост, я хочу уточнить, что это будет округлено, а не от нуля - отрицательные числа станут менее негативными, а положительные числа станут более положительными.