Qual é a melhor opção para dividir um número inteiro por 2?

406

Qual das seguintes técnicas é a melhor opção para dividir um número inteiro por 2 e por quê?

Técnica 1:

x = x >> 1;

Técnica 2:

x = x / 2;

Aqui xestá um número inteiro.

Abhineet
fonte
75
Se você realmente deseja atribuir o resultado xnovamente, nenhum deles é apropriado desta maneira: deve ser um x >>= 1ou x /= 2, dependendo do que você pretende expressar com a operação. Não porque é mais rápido (qualquer compilador moderno compilará todas as variantes equivalentes para montagem rápida e idêntica de qualquer maneira), mas porque é menos confuso.
leftaroundabout
33
Não concordo com o que foi dito a seguir. - Mas eu acho digno de nota que existe uma operação chamada mudança aritmética em muitas linguagens de programação que mantém o bit de sinal no lugar e, portanto, trabalha com valores assinados conforme o esperado. A sintaxe pode ser como x = x >>> 1. Observe também que, dependendo da plataforma e do compilador, pode ser bastante razoável otimizar manualmente divisões e multiplicações usando turnos. - Pensando em microcontroladores, por exemplo, sem suporte direto da ALU para multiplicação.
JimmyB
36
Eu prefiro x /= 2, porque x >>= 1parece muito com o ligamento monádico;)
fredoverflow
19
@leftaroundabout - Eu apenas considero muito mais legível escrever em x = x / 2vez de x /= 2. Preferência subjetiva talvez :)
JimmyB
8
@ HannoBinder: certamente subjetivo, em especial muitos hábitos. IMO, em um idioma em que todos os operadores aritméticos têm as ⬜=combinações, elas devem ser usadas sempre que possível. Ele remove o ruído e enfatiza o fato de que xé modificado , enquanto o =operador geral sugere que ele adquire um valor completamente novo, independente do antigo. - Sempre evitando os operadores combinados (de modo que seja legível por isso alguém que só sabe operadores matemáticos) pode ter seu ponto bem, mas depois que você precisa abandonar o extremamente útil ++, --, +=também.
leftaroundabout

Respostas:

847

Use a operação que melhor descreve o que você está tentando fazer.

  • Se você estiver tratando o número como uma sequência de bits, use deslocamento de bits.
  • Se você o estiver tratando como um valor numérico, use a divisão.

Observe que eles não são exatamente equivalentes. Eles podem fornecer resultados diferentes para números inteiros negativos. Por exemplo:

-5 / 2  = -2
-5 >> 1 = -3

(ideona)

Mark Byers
fonte
20
A pergunta original também era vaga sobre o termo "melhor". 'Melhor' em termos de velocidade, legibilidade, pergunta do exame para enganar os alunos, etc ... Na ausência de uma explicação do que 'melhor' significa, esta parece ser a resposta mais correta.
Ray
47
No C ++ 03, ambos são implementados para números negativos e podem fornecer os mesmos resultados. No C ++ 11, a divisão é bem definida para números negativos, mas a mudança ainda é definida pela implementação.
James Kanze
2
Embora a definição de / seja implementação (seja arredondada para cima ou para baixo para números negativos) definida nos primeiros padrões C. Deve sempre ser consistente com% (operador de módulo / restante).
Ctrl-alt-delor
7
"Implementação definida" significa que o implementador do compilador pôde escolher entre várias opções de implementação, geralmente com restrições substanciais. Aqui, uma restrição é que os operadores %e /devem ser consistentes para os operandos positivos e negativos, para que isso ocorra (a/b)*b+(a%b)==aindependentemente dos sinais de ae b. Geralmente, o autor faz escolhas que obtêm o melhor desempenho possível da CPU.
RBerteig
6
Então todo mundo que diz "o compilador irá convertê-lo em um turno de qualquer maneira" está errado, certo? A menos que o compilador pode garantir que você está lidando com um número inteiro não negativo (ou ele é uma constante ou é um int não assinado), não pode alterá-lo para uma mudança
Kip
225

O primeiro parece dividir? Não. Se você deseja dividir, use x / 2. O compilador pode otimizá-lo para usar a troca de bits, se possível (é chamado de redução de força), o que torna uma micro-otimização inútil se você fizer isso por conta própria.

Cat Plus Plus
fonte
15
Muitos compiladores não transformarão a divisão por potência de dois em um deslocamento de bits. Isso seria uma otimização incorreta para números inteiros assinados. Você deve tentar examinar a saída do assembly do seu compilador e ver por si mesmo.
ExDM69
1
O IIRC I usou isso para tornar a redução paralela mais rápida no CUDA (evitar div inteiro). No entanto, isso foi há mais de um ano, eu me pergunto o quão inteligentes os compiladores CUDA são hoje em dia.
Nils
9
@ exDM69: Muitos compiladores fazem isso mesmo para números inteiros assinados e apenas os ajustam de acordo com a assinatura. Uma boa ferramenta para brincar com essas coisas é esta: tinyurl.com/6uww253
PlasmaHH
19
@ exDM69: E isso é relevante, como? Eu disse "se possível", não "sempre". Se a otimização estiver incorreta, fazê-lo manualmente não o tornará correto (mais como mencionado, o GCC é inteligente o suficiente para descobrir a substituição adequada dos números inteiros assinados).
Cat Plus Plus,
4
Olhando para a página da WikiPedia, isso é aparentemente controverso, mas eu não chamaria isso de redução de força. Uma redução de força ocorre quando, em um loop, você reduz de, por exemplo, a multiplicação para a adição, adicionando valores anteriores ao loop. Isso é mais uma otimização do olho mágico, que os compiladores podem fazer de maneira bastante confiável.
SomeCallMeTim
189

Para empilhar: há muitas razões para favorecer o uso x = x / 2; Aqui estão algumas:

  • expressa sua intenção com mais clareza (supondo que você não esteja lidando com bits de registro de twiddling ou algo assim)

  • o compilador reduzirá isso para uma operação de turno de qualquer maneira

  • mesmo que o compilador não o reduza e escolha uma operação mais lenta que a mudança, a probabilidade de que isso acabe afetando o desempenho do seu programa de uma maneira mensurável é muito pequena (e se isso o afetar de forma mensurável, você terá uma experiência real). razão para usar um turno)

  • se a divisão fizer parte de uma expressão maior, é mais provável que você tenha a precedência correta se usar o operador de divisão:

    x = x / 2 + 5;
    x = x >> 1 + 5;  // not the same as above
    
  • aritmética assinada pode complicar ainda mais o problema de precedência mencionado acima

  • para reiterar - o compilador já fará isso por você de qualquer maneira. De fato, ele converterá a divisão por uma constante em uma série de turnos, somas e multiplicações para todos os tipos de números, não apenas para potências de dois. Veja esta pergunta para obter links para mais informações sobre isso.

Em resumo, você não compra nada codificando uma mudança quando realmente pretende multiplicar ou dividir, exceto, talvez, uma maior possibilidade de introduzir um bug. Faz uma vida desde que os compiladores não eram inteligentes o suficiente para otimizar esse tipo de coisa para uma mudança quando apropriado.

Michael Burr
fonte
5
Também vale a pena acrescentar que, embora existam regras de precedência, não há nada errado em usar parênteses. Ao reformular algum código de produção, vi algo do formulário a/b/c*d(onde a..das variáveis ​​numéricas são denotadas) em vez de muito mais legível (a*d)/(b*c).
1
O desempenho e as otimizações dependem do compilador e do destino. Por exemplo, eu trabalho para um microcontrolador em que algo maior que -O0 é desativado, a menos que você compre o compilador comercial, portanto o compilador definitivamente não transformará a divisão em turnos de bits. Além disso, o deslocamento de bits leva um ciclo e a divisão leva 18 ciclos nesse objetivo e, como a velocidade do clock dos microcontroladores é bastante baixa, isso pode ser um impacto perceptível no desempenho (mas depende do seu código - você definitivamente deve usar / até que o perfil o informe seu problema a)!
4
@JackManey, se houver qualquer possibilidade de que a*dou b*ciria produzir um estouro, a forma menos legível não é equivalente e tem uma vantagem óbvia. PS Concordo que os parênteses são seu melhor amigo.
Mark Ransom
@ MarkRansom - Um ponto justo (apesar de eu ter encontrado o a/b/c*dcódigo R - em um contexto em que o estouro significaria que algo estava seriamente errado com os dados - e não em, digamos, um bloco crítico de desempenho do código C).
O código x=x/2;é apenas "mais claro" do que x>>=1se xnunca for um número negativo ímpar ou se não se importar com erros pontuais. Caso contrário, x=x/2;e x>>=1;ter significados diferentes. Se o que se precisa é o valor calculado x>>=1, eu consideraria isso mais claro que x = (x & ~1)/2ou x = (x < 0) ? (x-1)/2 : x/2ou qualquer outra formulação que eu possa pensar em usar a divisão por dois. Da mesma forma, se é necessário o valor calculado por x/=2, isso é mais claro que ((x + ((unsigned)x>>31)>>1).
Supercat ''
62

Qual é a melhor opção e por que dividir o número inteiro por 2?

Depende do que você quer dizer com melhor .

Se você deseja que seus colegas o odeiem ou dificulte a leitura do código, eu definitivamente aceitaria a primeira opção.

Se você deseja dividir um número por 2, vá com o segundo.

Os dois não são equivalentes, eles não se comportam da mesma forma se o número for negativo ou dentro de expressões maiores - o deslocamento de bits tem precedência menor que +ou -, a divisão tem precedência mais alta.

Você deve escrever seu código para expressar qual é sua intenção. Se o desempenho é sua preocupação, não se preocupe, o otimizador faz um bom trabalho nesse tipo de micro-otimização.

Luchian Grigore
fonte
58

Basta usar o split ( /), presumindo que seja mais claro. O compilador otimizará adequadamente.

justin
fonte
34
O compilador deve otimizar adequadamente.
Noctis Skytower
12
Se o compilador não otimizar adequadamente, você deve usar um compilador melhor.
1811 David Stone
3
@ DavidStone: Em quais processadores um compilador pode otimizar a divisão de um número inteiro possivelmente negativo assinado por qualquer constante diferente de 1 para ser tão eficiente quanto uma mudança?
Supercat 01/11
1
@ supercat: Esse é um bom ponto. Obviamente, você pode armazenar o valor em um número inteiro não assinado (que eu sinto ter uma reputação muito pior do que deveria quando combinado com avisos de incompatibilidade assinados / não assinados), e a maioria dos compiladores também tem uma maneira de dizer a eles para assumir que algo é verdadeiro ao otimizar . Eu preferiria agrupar isso em uma macro de compatibilidade e ter algo como ASSUME(x >= 0); x /= 2;mais x >>= 1;, mas esse ainda é um ponto importante a ser abordado.
David Stone
39

Concordo com outras respostas que você deve favorecer x / 2porque sua intenção é mais clara e o compilador deve otimizá-lo para você.

No entanto, outro motivo para preferir o x / 2excesso x >> 1é que o comportamento de >>depende da implementação se xfor assinado inte for negativo.

Na seção 6.5.7, ponto 5 da norma ISO C99:

O resultado E1 >> E2é posições de bits E1deslocadas à direita E2. Se E1tiver um tipo não assinado ou E1um tipo assinado e um valor não negativo, o valor do resultado é parte integrante do quociente de E1/ 2 E2. Se E1tiver um tipo assinado e um valor negativo, o valor resultante será definido pela implementação.

jamesdlin
fonte
3
Vale a pena observar que o comportamento que muitas implementações definem para x>>scalepowernúmeros negativos será exatamente o necessário para dividir um valor por uma potência de dois para fins como renderização de tela, enquanto o uso x/scalefactorserá errado a menos que se aplique correções a valores negativos.
Supercat ''
32

x / 2é mais claro e x >> 1não é muito mais rápido (de acordo com uma micro-referência, cerca de 30% mais rápido para uma Java JVM). Como outros observaram, para números negativos o arredondamento é um pouco diferente; portanto, você deve considerar isso quando quiser processar números negativos. Alguns compiladores podem converter automaticamente x / 2para x >> 1se souberem que o número não pode ser negativo (mesmo que eu não pudesse verificar isso).

Even x / 2pode não usar a instrução da CPU de divisão (lenta), porque alguns atalhos são possíveis , mas ainda é mais lento que x >> 1.

(Este é um C / C ++ pergunta, outras linguagens de programação têm mais operadores. Para Java, há também o deslocamento para a direita sem sinal, x >>> 1que é novamente diferente. Ele permite calcular corretamente o valor médio (média) de dois valores, de modo que (a + b) >>> 1a vontade retorne o valor médio mesmo para valores muito grandes de ae bIsso é necessário, por exemplo, para pesquisa binária se os índices da matriz puderem ser muito grandes. Houve um erro em muitas versões da pesquisa binária , porque eles costumavam (a + b) / 2calcular a média. A solução correta é usar em seu (a + b) >>> 1lugar.)

Thomas Mueller
fonte
1
Compiladores não pode converter x/2para x>>1nos casos em que xpode ser negativo. Se o que se quer é o valor que x>>1calcularia, isso quase certamente será mais rápido do que qualquer expressão envolvendo x/2que calcule o mesmo valor.
Supercat ''
Você está certo. Um compilador só pode converter x/2para x>>1se ele souber que o valor não é negativo. Vou tentar atualizar minha resposta.
Thomas Mueller
os compiladores ainda evitam uma divinstrução, convertendo x/2para (x + (x<0?1:0)) >> 1(onde >> é um deslocamento aritmético para a direita, que muda em bits de sinal). São necessárias 4 instruções: copie o valor, shr (para obter apenas o bit do sinal em um reg), adicione sar. goo.gl/4F8Ms4
Peter Cordes
A pergunta está marcada como C e C ++.
Josh Sanford
22

Knuth disse:

Otimização prematura é a raiz de todo o mal.

Então eu sugiro usar x /= 2;

Dessa forma, o código é fácil de entender e também acho que a otimização dessa operação dessa forma, não significa uma grande diferença para o processador.

Ivan Californias
fonte
4
O que você consideraria o método preferido de reduzir um número em uma potência de dois, se alguém quiser que os números inteiros mantenham o axioma (que se aplica a números naturais e números reais) que (n + d) / d = (n / d) + 1? Violações que axioma ao dimensionar gráficos causam "costuras" visíveis no resultado. Se alguém quer algo uniforme e quase simétrico em relação a zero, (n+8)>>4funciona bem. Você pode oferecer uma abordagem tão clara ou eficiente sem usar o turno certo assinado?
precisa
19

Dê uma olhada na saída do compilador para ajudá-lo a decidir. Eu executei este teste no x86-64 com o
gcc (GCC) 4.2.1 20070719 [FreeBSD]

Veja também as saídas do compilador online no godbolt .

O que você vê é que o compilador usa uma sarlinstrução (desvio aritmético para a direita) em ambos os casos, portanto reconhece a semelhança entre as duas expressões. Se você usar a divisão, o compilador também precisará ajustar os números negativos. Para fazer isso, ele muda o bit de sinal para o bit de menor ordem e o adiciona ao resultado. Isso corrige a questão de um por um ao mudar números negativos, em comparação com o que uma divisão faria.
Como o caso de divisão faz 2 turnos, enquanto o caso explícito de turno apenas um, podemos agora explicar algumas das diferenças de desempenho medidas por outras respostas aqui.

Código C com saída de montagem:

Para dividir, sua entrada seria

int div2signed(int a) {
  return a / 2;
}

e isso compila para

    movl    %edi, %eax
    shrl    $31, %eax
    addl    %edi, %eax
    sarl    %eax
    ret

Da mesma forma para o turno

int shr2signed(int a) {
  return a >> 1;
}

com saída:

    sarl    %edi
    movl    %edi, %eax
    ret
Michael Donohue
fonte
Dependendo do que se está fazendo, ele pode corrigir o erro de um por um ou pode causar um erro de um por um (comparado com o que é realmente necessário), o que exigirá o uso de mais código para corrigi-lo. Se o que se deseja é um resultado mínimo, uma mudança à direita é mais rápida e fácil do que qualquer outra alternativa que eu conheça.
Supercat #
Se você precisa de um piso, é improvável você descreveria o que você quer como "dividindo por 2"
Michael Donohue
A divisão de números naturais e números reais sustenta o axioma que (n + d) / d = (n / d) +1. A divisão de números reais também sustenta (-n) / d = - (n / d), um axioma que não tem sentido nos números naturais. Não é possível ter um operador de divisão que esteja fechado em números inteiros e defenda os dois axiomas. A meu ver, dizer que o primeiro axioma deve valer para todos os números e o segundo apenas para reais parece mais natural do que dizer que o primeiro deve valer para números inteiros ou reais, mas não para números inteiros. Além disso, estou curioso para saber em que casos o segundo axioma é realmente útil .
Supercat #
1
Um método de divisão inteira que satisfaça o primeiro axioma dividirá a linha numérica em regiões de tamanho d. Esse particionamento é útil para muitos propósitos. Mesmo se alguém preferir ter o ponto de interrupção em algum lugar que não seja entre 0 e -1, adicionar um deslocamento o moverá. Uma divisão inteira que satisfaça o segundo axioma dividirá a linha numérica em regiões que são principalmente de tamanho d, mas uma delas é de tamanho 2*d-1. Não exatamente divisões "iguais". Você pode oferecer sugestões de quando a partição ímpar é realmente útil?
Supercat #
Sua saída do compilador para shr2signed está incorreta. O gcc no x86 escolhe implementar >> de números inteiros assinados com turnos aritméticos ( sar). goo.gl/KRgIkb . Esta publicação na lista de discussão ( gcc.gnu.org/ml/gcc/2000-04/msg00152.html ) confirma que o gcc usa historicamente turnos aritméticos para entradas assinadas, portanto, é altamente improvável que o FreeBSD gcc 4.2.1 tenha usado turno não assinado. Atualizei sua postagem para corrigir isso e o parágrafo anterior dizendo que ambos usavam shr, quando na verdade é SAR que ambos usam. O SHR é como extrai o bit de sinal para o /caso. Também incluiu um link godbolt.
Peter Cordes
15

Apenas uma nota adicional -

x * = 0,5 geralmente será mais rápido em alguns idiomas baseados em VM - principalmente actionscript, pois a variável não precisará ser verificada quanto à divisão por 0.

ansiart
fonte
2
@ minitech: Esse é um teste tão ruim. Todo o código no teste é constante. Antes que o código seja JITado, ele eliminará todas as constantes.
@ M28: Eu tinha certeza que os internos do jsPerf (ou seja eval) faziam isso acontecer de novo a cada vez. Independentemente disso, sim, é um teste muito ruim, porque é uma otimização muito boba.
Ry-
13

Use x = x / 2; OR x /= 2;Porque é possível que um novo programador trabalhe nele no futuro. Portanto, será mais fácil descobrir o que está acontecendo na linha de código. Todos podem não estar cientes dessas otimizações.

Imdad
fonte
12

Estou dizendo com o objetivo de programar competições. Geralmente eles têm entradas muito grandes, onde a divisão por 2 ocorre muitas vezes e sabe-se que a entrada é positiva ou negativa.

x >> 1 será melhor que x / 2. Eu verifiquei no ideone.com executando um programa em que ocorreram mais de 10 ^ 10 divisões por 2 operações. x / 2 levou quase 5,5s enquanto x >> 1 levou quase 2,6s para o mesmo programa.

Shashwat Kumar
fonte
1
Para valores não assinados, um compilador deve otimizar x/2para x>>1. Para valores assinados, quase todas as implementações definem x>>1ter um significado equivalente a, x/2mas podem ser computadas mais rapidamente quando xpositivo, e é útil diferente de x/2quando xnegativo.
Supercat #
12

Eu diria que há várias coisas a considerar.

  1. O deslocamento de bits deve ser mais rápido, pois não é realmente necessário um cálculo especial para mudar os bits; no entanto, como apontado, existem problemas em potencial com números negativos. Se você tiver números positivos e estiver procurando velocidade, eu recomendaria o deslocamento de bits.

  2. O operador de divisão é muito fácil para os humanos lerem. Portanto, se você estiver procurando legibilidade de código, poderá usá-lo. Observe que o campo da otimização do compilador já percorreu um longo caminho, facilitando a leitura e compreensão do código, é uma boa prática.

  3. Dependendo do hardware subjacente, as operações podem ter velocidades diferentes. A lei de Amdal é tornar o caso comum rápido. Portanto, você pode ter um hardware que pode executar operações diferentes mais rapidamente do que outros. Por exemplo, multiplicar por 0,5 pode ser mais rápido que dividir por 2. (Concedido, você pode precisar usar o piso da multiplicação se desejar impor a divisão inteira).

Se você busca desempenho puro, eu recomendaria a criação de alguns testes que poderiam executar as operações milhões de vezes. Faça a amostra da execução várias vezes (o tamanho da amostra) para determinar qual é estatisticamente melhor com seu SO / Hardware / Compilador / Código.

James Oravec
fonte
2
"Bitshift deve ser mais rápido". compiladores irá otimizar divisões em bitshifts
Trevor Hickey
Espero que o faria, mas se não tiver acesso à fonte do compilador, você não pode ter certeza :)
James Oravec
1
Eu também recomendaria o deslocamento de bits se a implementação da pessoa lidar com isso da maneira mais comum e da maneira como alguém deseja lidar com números negativos corresponde ao que >>faz e não ao que /faz.
Supercat ''
12

No que diz respeito à CPU, as operações de troca de bits são mais rápidas que as operações de divisão. No entanto, o compilador sabe disso e otimizará apropriadamente na medida do possível, para que você possa codificar da maneira que fizer mais sentido e ficar mais tranquilo sabendo que seu código está sendo executado com eficiência. Mas lembre-se de que um unsigned int(em alguns casos) pode ser otimizado melhor do que um intpor razões apontadas anteriormente. Se você não precisar de aritmética assinada, não inclua o bit de sinal.

tylerl
fonte
11

x = x / 2; é o código adequado para uso .. mas uma operação depende do seu próprio programa de como a saída que você deseja produzir.

Gooner
fonte
11

Torne suas intenções mais claras ... por exemplo, se você deseja dividir, use x / 2 e deixe o compilador otimizá-lo para mudar de operador (ou qualquer outra coisa).

Os processadores de hoje não permitem que essas otimizações tenham impacto no desempenho de seus programas.

Atul Kumar
fonte
10

A resposta para isso dependerá do ambiente em que você estiver trabalhando.

  • Se você está trabalhando em um microcontrolador de 8 bits ou qualquer coisa sem suporte de hardware para multiplicação, pouco deslocamento é esperado e comum, e enquanto o compilador irá quase certamente transformar x /= 2em x >>= 1, a presença de um símbolo de divisão vai aumentar mais as sobrancelhas naquele ambiente de usando uma mudança para efetuar uma divisão.
  • Se você estiver trabalhando em um ambiente crítico de desempenho ou em uma seção de código, ou se seu código puder ser compilado com a otimização do compilador desativada, x >>= 1um comentário explicando seu raciocínio provavelmente será o melhor apenas para fins de clareza de propósito.
  • Se você não estiver em uma das condições acima, torne seu código mais legível simplesmente usando x /= 2. É melhor salvar o próximo programador que, por acaso, examinar seu código nos 10 segundos de operação dupla, do que provar desnecessariamente que sabia que o turno era mais eficiente na otimização do compilador.

Todos estes assumem números inteiros não assinados. A mudança simples provavelmente não é o que você deseja assinar. Além disso, DanielH traz um bom argumento sobre o uso x *= 0.5de determinadas linguagens como o ActionScript.

gkimsey
fonte
8

mod 2, teste para = 1. não sei a sintaxe em c. mas isso pode ser mais rápido.

circusdei
fonte
7

geralmente o turno certo divide:

q = i >> n; is the same as: q = i / 2**n;

isso às vezes é usado para acelerar os programas à custa da clareza. Eu não acho que você deveria fazer isso. O compilador é inteligente o suficiente para executar a aceleração automaticamente. Isso significa que fazer uma mudança não ganha nada à custa da clareza .

Dê uma olhada nesta página da Practical C ++ Programming.

Mouna Cheikhna
fonte
Se alguém quiser calcular o valor que, por exemplo (x+128)>>8, calcularia valores xnão próximos do máximo, como poderia fazê-lo de forma concisa sem um turno? Observe que (x+128)/256não vai funcionar. Você conhece alguma expressão legal que o faça?
Supercat ''
7

Obviamente, se você estiver escrevendo seu código para o próximo usuário que o lê, procure a clareza de "x / 2".

No entanto, se a velocidade é seu objetivo, tente de duas maneiras e cronometrar os resultados. Alguns meses atrás, trabalhei em uma rotina de convolução de bitmap que envolvia percorrer uma matriz de números inteiros e dividir cada elemento por 2. Fiz todo o tipo de coisas para otimizá-lo, incluindo o velho truque de substituir "x >> 1" por "x" / 2 ".

Quando cronometrei os dois sentidos, descobri, para minha surpresa, que x / 2 era mais rápido que x >> 1

Isso estava usando o Microsoft VS2008 C ++ com as otimizações padrão ativadas.

Chris Bennet
fonte
4

Em termos de desempenho. As operações de turno da CPU são significativamente mais rápidas que os códigos operacionais divididos. Assim, dividir por dois ou multiplicar por 2 etc, todos se beneficiam das operações de turno.

Quanto à aparência. Como engenheiros, quando nos tornamos tão apegados aos cosméticos que nem mesmo as mulheres bonitas usam! :)

Farjad
fonte
3

X / Y é o correto ... e ">>" operador de deslocamento .. se queremos dois dividir um número inteiro, podemos usar (/) operador de dividendos. O operador shift é usado para mudar os bits.

x = x / 2; x / = 2; podemos usar assim ..

menino de chocolate
fonte
0

Enquanto x >> 1 é mais rápido que x / 2, o uso adequado de >> ao lidar com valores negativos é um pouco mais complicado. Requer algo semelhante ao seguinte:

// Extension Method
public static class Global {
    public static int ShiftDivBy2(this int x) {
        return (x < 0 ? x + 1 : x) >> 1;
    }
}
Darin
fonte