Dados los valores enteros x
y y
, C y C ++, ambos devuelven como cociente q = x/y
el piso del equivalente de coma flotante. Estoy interesado en un método para devolver el techo en su lugar. Por ejemplo, ceil(10/5)=2
y ceil(11/5)=3
.
El enfoque obvio implica algo como:
q = x / y;
if (q * y < x) ++q;
Esto requiere una comparación y multiplicación extra; y otros métodos que he visto (de hecho) involucran la conversión como float
o double
. ¿Existe un método más directo que evite la multiplicación adicional (o una segunda división) y la ramificación, y que también evite la conversión como un número de coma flotante?
q = x/y + (x % y != 0);
es suficienteRespuestas:
Para números positivos
Para resumir ...
o (evitando el desbordamiento en x + y)
fuente
x/y
es el techo de la división. C90 no especificó cómo redondear, y tampoco creo que el estándar actual de C ++ lo haga.q = x / y;
Para números positivos:
fuente
La respuesta de Sparky es una forma estándar de resolver este problema, pero como también escribí en mi comentario, corre el riesgo de desbordamientos. Esto se puede resolver utilizando un tipo más amplio, pero ¿qué pasa si desea dividir
long long
s?La respuesta de Nathan Ernst proporciona una solución, pero implica una llamada a la función, una declaración de variable y un condicional, lo que lo hace no más corto que el código OP y probablemente aún más lento, porque es más difícil de optimizar.
Mi solución es esta:
Será un poco más rápido que el código OP, porque el módulo y la división se realizan utilizando la misma instrucción en el procesador, porque el compilador puede ver que son equivalentes. Al menos gcc 4.4.1 realiza esta optimización con el indicador -O2 en x86.
En teoría, el compilador podría incluir la llamada de función en el código de Nathan Ernst y emitir lo mismo, pero gcc no hizo eso cuando lo probé. Esto podría deberse a que vincularía el código compilado a una única versión de la biblioteca estándar.
Como nota final, nada de esto importa en una máquina moderna, excepto si está en un circuito extremadamente cerrado y todos sus datos están en registros o en el caché L1. De lo contrario, todas estas soluciones serán igualmente rápidas, excepto posiblemente la de Nathan Ernst, que podría ser significativamente más lenta si la función tiene que ser obtenida de la memoria principal.
fuente
q = (x > 0)? 1 + (x - 1)/y: (x / y);
q = x / y + (x % y > 0);
es más fácil que la? :
expresión?Puede usar la
div
función en cstdlib para obtener el cociente y el resto en una sola llamada y luego manejar el techo por separado, como en el siguientefuente
return res.quot + !!res.rem;
:)¿Qué tal esto? (requiere y no negativo, así que no use esto en el raro caso de que y sea una variable sin garantía de no negatividad)
Reduje
y/y
a uno, eliminando el términox + y - 1
y con él cualquier posibilidad de desbordamiento.Evito
x - 1
envolviendo alrededor cuandox
es un tipo sin signo y contiene cero.Para firmado
x
, negativo y cero aún se combinan en un solo caso.Probablemente no sea un gran beneficio en una CPU moderna de uso general, pero esto sería mucho más rápido en un sistema integrado que cualquiera de las otras respuestas correctas.
fuente
Hay una solución tanto para positivo como negativo,
x
pero solo para positivoy
con solo 1 división y sin ramas:Tenga en cuenta que si
x
es positivo, entonces la división es hacia cero, y debemos agregar 1 si el recordatorio no es cero.Si
x
es negativo, entonces la división es hacia cero, eso es lo que necesitamos, y no agregaremos nada porquex % y
no es positivofuente
Esto funciona para números positivos o negativos:
Si hay un resto, comprueba si
x
yy
son del mismo signo, y añade1
en consecuencia.fuente
Hubiera preferido comentar pero no tengo un representante lo suficientemente alto.
Hasta donde yo sé, para argumentos positivos y un divisor que es una potencia de 2, esta es la forma más rápida (probado en CUDA):
Solo para argumentos positivos genéricos, tiendo a hacerlo así:
fuente
q = x/y + !!(x % y);
comparaq = x/y + (x % y == 0);
y lasq = (x + y - 1) / y;
soluciones en cuanto al rendimiento en CUDA contemporáneo.forma genérica simplificada,
Para una respuesta más genérica, C ++ funciona para la división de enteros con una estrategia de redondeo bien definida
fuente
Compilar con O3, el compilador realiza bien la optimización.
fuente