>> é a mudança aritmética certa, >>> é a mudança lógica certa.
Em um deslocamento aritmético, o bit de sinal é estendido para preservar a assinatura do número.
Por exemplo: -2 representado em 8 bits seria 11111110(porque o bit mais significativo tem peso negativo). Mudar um pouco para a direita usando a mudança aritmética daria a você 11111111, ou -1. O deslocamento lógico para a direita, no entanto, não se importa que o valor possa representar um número assinado; simplesmente move tudo para a direita e preenche da esquerda com 0s. Mudar nosso -2 para a direita usando um deslocamento lógico daria 01111111.
Embora eu concorde e aprecie que as mudanças aritméticas possam ser usadas para multiplicar números assinados 2^k, acho estranho que essa seja a resposta de todos. Uma cadeia de bits não é um número e >>sempre pode ser usada em qualquer cadeia de bits: sempre faz a mesma coisa, independentemente do papel que a cadeia de bits está desempenhando e independentemente do conceito de 'sinal'. Seria bom estender sua já ótima resposta com uma discussão do caso em que seu operando não está sendo interpretado como um número assinado? A minha reclamação faz sentido?
Ziggy
11
Por que você diz que uma sequência de bits não é um número? Você diria que uma sequência de dígitos decimais não é um número?
Danben
4
@danben Discutir se é ou não um número, só faz sentido se você o vincular a um contexto. Se a internet é apenas eletricidade, concordo que uma String é apenas um número.
Bvdb 17/08/2015
11
@danben mas, na verdade, acho que o que Ziggy estava realmente se referindo (imho), é que um Stringtambém pode ser considerado um char[]. Ele não está dizendo que a charnão é um número; ele está apenas dizendo que é um número não assinado . Eu acho que é onde ele está perdido.
bvdb
5
@Ziggy está certo: nem toda sequência de bits é um número e nem toda sequência de dígitos decimais é um número. Por exemplo: números de telefone, códigos postais (em muitos países) etc. são cadeias de dígitos decimais, mas não faz sentido adicioná-las, subtraí-las ou multiplicá-las, para que não sejam realmente números. Por acaso são sequências de dígitos decimais, mas devem ser tratadas como sequências de caracteres. (Os códigos postais no Canadá e no Reino Unido contêm letras e dígitos.)
jcsahnwaldt disse GoFundMonica
102
>>>é turno não assinado; ele irá inserir 0.>> está assinado e estenderá o bit de sinal.
Os operadores de turno incluem turno esquerdo <<, turno direito assinado >>e turno direito não assinado>>> .
O valor de n>>sé posições de bits ndeslocadas à direita scom extensão de sinal .
O valor de n>>>sé posições de bits ndeslocadas à direita scom extensão zero .
System.out.println(Integer.toBinaryString(-1));// prints "11111111111111111111111111111111"System.out.println(Integer.toBinaryString(-1>>16));// prints "11111111111111111111111111111111"System.out.println(Integer.toBinaryString(-1>>>16));// prints "1111111111111111"
Para tornar as coisas mais claras, adicionando contrapartida positiva
System.out.println(Integer.toBinaryString(121));// prints "1111001"System.out.println(Integer.toBinaryString(121>>1));// prints "111100"System.out.println(Integer.toBinaryString(121>>>1));// prints "111100"
Como é positivo, os turnos assinados e não assinados adicionarão 0 à esquerda, na maioria dos bits.
O operador de mudança à direita não assinado ">>>" muda um zero para a posição mais à esquerda, enquanto a posição mais à esquerda após ">>" depende da extensão do sinal.
Suponho que >>>não esteja assinado, mas por que 7>>32=7? Corri um loop que fazia um turno de cada vez e vi que, depois dos 32turnos, ele voltava a 7. A única maneira de fazer sentido é que, para cada número alterado, ele entra em um "círculo externo". Após os 32turnos, voltou de alguma forma à sua posição, mas obviamente isso ainda não faz sentido. O que está acontecendo?
Ian Limarta
@IanLimarta Não faz? Acabei de receber 0. ( for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));) Se você quer dizer por que >>32ele retorna o valor original, veja isso .
Moira
Eu sinto Muito. Eu quis dizer por que '7 >>> 32 = 7'.
Ian Limarta 31/03
40
O deslocamento lógico para a direita ( v >>> n) retorna um valor no qual os bits vforam deslocados para a direita pelas nposições dos bits e os 0 são deslocados do lado esquerdo. Considere mudar os valores de 8 bits, escritos em binário:
01111111>>>2=0001111110000000>>>2=00100000
Se interpretarmos os bits como um número inteiro não negativo não assinado, o deslocamento lógico para a direita terá o efeito de dividir o número pela potência correspondente de 2. No entanto, se o número estiver na representação de complemento de dois, o deslocamento lógico à direita não dividirá corretamente os números negativos. . Por exemplo, o segundo deslocamento à direita acima muda de 128 para 32 quando os bits são interpretados como números não assinados. Mas muda de -128 para 32 quando, como é típico em Java, os bits são interpretados no complemento de dois.
Portanto, se você estiver mudando para dividir por uma potência de dois, deseja o deslocamento aritmético para a direita ( v >> n). Ele retorna um valor no qual os bits vforam deslocados para a direita porn posições dos bits e as cópias do bit mais à esquerda de v são deslocadas do lado esquerdo:
01111111>>2=0001111110000000>>2=11100000
Quando os bits são um número na representação do complemento de dois, o deslocamento aritmético para a direita tem o efeito de dividir por uma potência de dois. Isso funciona porque o bit mais à esquerda é o bit de sinal. Dividir por um poder de dois deve manter o sinal igual.
O padrão de bits é dado pelo operando do lado esquerdo e o número de posições a serem deslocadas pelo operando do lado direito. O operador de mudança à direita não assinado >>>muda o zero para a posição mais à esquerda ,
enquanto a posição mais à esquerda após >> depende da extensão do sinal.
Em palavras simples, >>>sempre desloca um zero para a posição mais à esquerda, enquanto >>desloca com base no sinal do número, ou seja, 1 para número negativo e 0 para número positivo.
Por exemplo, tente com números negativos e positivos.
int c =-153;System.out.printf("%32s%n",Integer.toBinaryString(c >>=2));System.out.printf("%32s%n",Integer.toBinaryString(c <<=2));System.out.printf("%32s%n",Integer.toBinaryString(c >>>=2));System.out.println(Integer.toBinaryString(c <<=2));System.out.println();
c =153;System.out.printf("%32s%n",Integer.toBinaryString(c >>=2));System.out.printf("%32s%n",Integer.toBinaryString(c <<=2));System.out.printf("%32s%n",Integer.toBinaryString(c >>>=2));System.out.printf("%32s%n",Integer.toBinaryString(c <<=2));
Obrigado. Só quero adicionar um comentário para referenciar a representação de bits para Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, 1 . por exemplo System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0')):; Integer.MAX_VALUE : 01111111111111111111111111111111;Integer.MIN_VALUE : 10000000000000000000000000000000;-1 : 11111111111111111111111111111111;0 : 00000000000000000000000000000000;1 : 00000000000000000000000000000001
Andy Dong
6
O operador lógico de deslocamento à direita ( >>> N) desloca os bits para a direita pelas posições N, descartando o bit de sinal e preenchendo os N bits mais à esquerda com zeros. Por exemplo:
-1(in 32-bit):11111111111111111111111111111111
depois que uma >>> 1operação se tornar:
2147483647:01111111111111111111111111111111
O operador aritmético de deslocamento à direita ( >> N) também desloca os bits para a direita pelas posições N, mas preserva o bit de sinal e preenche os N bits mais à esquerda com 1's. Por exemplo:
Respostas:
>>
é a mudança aritmética certa,>>>
é a mudança lógica certa.Em um deslocamento aritmético, o bit de sinal é estendido para preservar a assinatura do número.
Por exemplo: -2 representado em 8 bits seria
11111110
(porque o bit mais significativo tem peso negativo). Mudar um pouco para a direita usando a mudança aritmética daria a você11111111
, ou -1. O deslocamento lógico para a direita, no entanto, não se importa que o valor possa representar um número assinado; simplesmente move tudo para a direita e preenche da esquerda com 0s. Mudar nosso -2 para a direita usando um deslocamento lógico daria01111111
.fonte
2^k
, acho estranho que essa seja a resposta de todos. Uma cadeia de bits não é um número e>>
sempre pode ser usada em qualquer cadeia de bits: sempre faz a mesma coisa, independentemente do papel que a cadeia de bits está desempenhando e independentemente do conceito de 'sinal'. Seria bom estender sua já ótima resposta com uma discussão do caso em que seu operando não está sendo interpretado como um número assinado? A minha reclamação faz sentido?String
também pode ser considerado umchar[]
. Ele não está dizendo que achar
não é um número; ele está apenas dizendo que é um número não assinado . Eu acho que é onde ele está perdido.>>>
é turno não assinado; ele irá inserir 0.>>
está assinado e estenderá o bit de sinal.Operadores de turno JLS 15.19
Para tornar as coisas mais claras, adicionando contrapartida positiva
Como é positivo, os turnos assinados e não assinados adicionarão 0 à esquerda, na maioria dos bits.
Perguntas relacionadas
1 >>> 32 == 1
fonte
Ambos estão no turno certo, mas
>>>
éunsigned
A partir da documentação :
fonte
>>>
não esteja assinado, mas por que7>>32=7
? Corri um loop que fazia um turno de cada vez e vi que, depois dos32
turnos, ele voltava a7
. A única maneira de fazer sentido é que, para cada número alterado, ele entra em um "círculo externo". Após os32
turnos, voltou de alguma forma à sua posição, mas obviamente isso ainda não faz sentido. O que está acontecendo?for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));
) Se você quer dizer por que>>32
ele retorna o valor original, veja isso .O deslocamento lógico para a direita (
v >>> n
) retorna um valor no qual os bitsv
foram deslocados para a direita pelasn
posições dos bits e os 0 são deslocados do lado esquerdo. Considere mudar os valores de 8 bits, escritos em binário:Se interpretarmos os bits como um número inteiro não negativo não assinado, o deslocamento lógico para a direita terá o efeito de dividir o número pela potência correspondente de 2. No entanto, se o número estiver na representação de complemento de dois, o deslocamento lógico à direita não dividirá corretamente os números negativos. . Por exemplo, o segundo deslocamento à direita acima muda de 128 para 32 quando os bits são interpretados como números não assinados. Mas muda de -128 para 32 quando, como é típico em Java, os bits são interpretados no complemento de dois.
Portanto, se você estiver mudando para dividir por uma potência de dois, deseja o deslocamento aritmético para a direita (
v >> n
). Ele retorna um valor no qual os bitsv
foram deslocados para a direita porn
posições dos bits e as cópias do bit mais à esquerda de v são deslocadas do lado esquerdo:Quando os bits são um número na representação do complemento de dois, o deslocamento aritmético para a direita tem o efeito de dividir por uma potência de dois. Isso funciona porque o bit mais à esquerda é o bit de sinal. Dividir por um poder de dois deve manter o sinal igual.
fonte
>>>
sempre colocará 0 no bit mais à esquerda, enquanto>>
colocará 1 ou 0, dependendo de qual seja o sinal.fonte
Leia mais sobre os operadores Bitwise e Bit Shift
O padrão de bits é dado pelo operando do lado esquerdo e o número de posições a serem deslocadas pelo operando do lado direito. O operador de mudança à direita não assinado
>>>
muda o zero para a posição mais à esquerda ,enquanto a posição mais à esquerda após
>>
depende da extensão do sinal.Em palavras simples,
>>>
sempre desloca um zero para a posição mais à esquerda, enquanto>>
desloca com base no sinal do número, ou seja, 1 para número negativo e 0 para número positivo.Por exemplo, tente com números negativos e positivos.
resultado:
fonte
System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0'))
:; Integer.MAX_VALUE :01111111111111111111111111111111;
Integer.MIN_VALUE :10000000000000000000000000000000;
-1 :11111111111111111111111111111111;
0 :00000000000000000000000000000000;
1 :00000000000000000000000000000001
O operador lógico de deslocamento à direita (
>>> N
) desloca os bits para a direita pelas posições N, descartando o bit de sinal e preenchendo os N bits mais à esquerda com zeros. Por exemplo:depois que uma
>>> 1
operação se tornar:O operador aritmético de deslocamento à direita (
>> N
) também desloca os bits para a direita pelas posições N, mas preserva o bit de sinal e preenche os N bits mais à esquerda com 1's. Por exemplo:depois que uma
>> 1
operação se tornar:fonte