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 daria 01111111
.
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 um char[]
. Ele não está dizendo que a char
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.
Os operadores de turno incluem turno esquerdo
<<
, turno direito assinado>>
e turno direito não assinado>>>
.O valor de
n>>s
é posições de bitsn
deslocadas à direitas
com extensão de sinal .O valor de
n>>>s
é posições de bitsn
deslocadas à direitas
com 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.
1 >>> 32 == 1
Ambos estão no turno certo, mas >>>
éunsigned
A partir da documentação :
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.
>>>
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 32
turnos, 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 32
turnos, voltou de alguma forma à sua posição, mas obviamente isso ainda não faz sentido. O que está acontecendo?
O deslocamento lógico para a direita ( v >>> n
) retorna um valor no qual os bits v
foram deslocados para a direita pelas n
posiçõ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 = 00011111
10000000 >>> 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 v
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:
01111111 >> 2 = 00011111
10000000 >> 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.
Leia mais sobre os operadores Bitwise e Bit Shift
>> Signed right shift
>>> Unsigned right 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.
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));
resultado:
11111111111111111111111111011001
11111111111111111111111101100100
111111111111111111111111011001
11111111111111111111111101100100
100110
10011000
100110
10011000
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:
-1 (in 32-bit): 11111111111111111111111111111111
depois que uma >>> 1
operaçã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:
-2 (in 32-bit): 11111111111111111111111111111110
depois que uma >> 1
operação se tornar:
-1: 11111111111111111111111111111111