Dados os valores inteiros x
e y
, C e C ++ retornam como quociente q = x/y
o piso do equivalente em ponto flutuante. Estou interessado em um método de devolver o teto. Por exemplo, ceil(10/5)=2
e ceil(11/5)=3
.
A abordagem óbvia envolve algo como:
q = x / y;
if (q * y < x) ++q;
Isso requer uma comparação e multiplicação extras; e outros métodos que eu vi (usados de fato) envolvem a transmissão como um float
ou double
. Existe um método mais direto que evite a multiplicação adicional (ou uma segunda divisão) e ramificação, e também evite a conversão como um número de ponto flutuante?
q = x/y + (x % y != 0);
é suficienteRespostas:
Para números positivos
Para arredondar ...
ou (evitando o estouro em x + y)
fonte
x/y
como o teto da divisão. O C90 não especificou como arredondar e também não acho que o padrão C ++ atual.q = x / y;
Para números positivos:
fonte
A resposta de Sparky é uma maneira padrão de resolver esse problema, mas como também escrevi no meu comentário, você corre o risco de estouros. Isso pode ser resolvido usando um tipo mais amplo, mas e se você quiser dividir
long long
s?A resposta de Nathan Ernst fornece uma solução, mas envolve uma chamada de função, uma declaração de variável e uma condicional, o que o torna não mais curto que o código dos OPs e provavelmente ainda mais lento, porque é mais difícil de otimizar.
Minha solução é esta:
Será um pouco mais rápido que o código de OPs, porque o módulo e a divisão são executados usando a mesma instrução no processador, porque o compilador pode ver que eles são equivalentes. Pelo menos o gcc 4.4.1 executa essa otimização com o sinalizador -O2 em x86.
Em teoria, o compilador pode incorporar a chamada de função no código de Nathan Ernst e emitir a mesma coisa, mas o gcc não fez isso quando o testei. Isso pode ocorrer porque vincularia o código compilado a uma única versão da biblioteca padrão.
Como observação final, nada disso importa em uma máquina moderna, exceto se você estiver em um loop extremamente rígido e todos os seus dados estiverem em registradores ou no cache L1. Caso contrário, todas essas soluções serão igualmente rápidas, exceto, possivelmente, as de Nathan Ernst, que podem ser significativamente mais lentas se a função precisar ser buscada na memória principal.
fonte
q = (x > 0)? 1 + (x - 1)/y: (x / y);
q = x / y + (x % y > 0);
é mais fácil do que? :
expressão?Você pode usar a
div
função no cstdlib para obter o quociente e o restante em uma única chamada e, em seguida, manipular o teto separadamente, como abaixofonte
return res.quot + !!res.rem;
:)Que tal agora? (requer y não negativo, portanto, não use isso em casos raros em que y é uma variável sem garantia de não negatividade)
Reduzi
y/y
a um, eliminando o termox + y - 1
e com ele qualquer chance de transbordar.Evito
x - 1
envolver quandox
é um tipo não assinado e contém zero.Para assinado
x
, negativo e zero ainda combinam em um único caso.Provavelmente não é um grande benefício para uma CPU moderna de uso geral, mas isso seria muito mais rápido em um sistema incorporado do que qualquer outra resposta correta.
fonte
Existe uma solução para positivo e negativo,
x
mas apenas para positivoy
com apenas 1 divisão e sem ramificações:Observe que se
x
for positivo, a divisão será em direção a zero e devemos adicionar 1 se o lembrete não for zero.Se
x
for negativo, a divisão é em direção a zero, é disso que precisamos e não adicionaremos nada porquex % y
não é positivofonte
Isso funciona para números positivos ou negativos:
Se houver um restante, verifica se há
x
ey
tem o mesmo sinal e adiciona de1
acordo.fonte
Eu preferiria comentar, mas não tenho um representante suficientemente alto.
Tanto quanto sei, para argumentos positivos e um divisor que é uma potência de 2, esta é a maneira mais rápida (testada no CUDA):
Apenas para argumentos positivos genéricos, costumo fazer o seguinte:
fonte
q = x/y + !!(x % y);
pilhas se comparamq = x/y + (x % y == 0);
e asq = (x + y - 1) / y;
soluções em termos de desempenho na CUDA contemporânea.formulário genérico simplificado,
Para uma resposta mais genérica, o C ++ funciona para divisão inteira com estratégia de arredondamento bem definida
fonte
Compilar com O3, O compilador executa bem a otimização.
fonte