Operadores Swift Bitwise e Bit Shift (com exemplos)

Neste tutorial, você aprenderá sobre diferentes operações bit a bit no Swift. Eles são usados ​​para cálculo de nível de bit em uma expressão.

Um bit é usado para denotar um dígito binário. Um dígito binário pode ter dois valores possíveis, 0 ou 1. Como um programador de nível iniciante, você não precisa trabalhar com operações no nível de bits.

Trabalhar com tipos de dados primitivos como: integer, float, boolean, string etc é o suficiente. Você pode precisar trabalhar no nível de bits quando estiver lidando com programação de baixo nível.

O Swift fornece um rico conjunto de operadores, além dos operadores básicos, para manipular bits. Esses operadores são semelhantes aos operadores lógicos, exceto que funcionam em representações binárias de dados (bits).

Operadores bit a bit são operadores usados ​​para alterar bits individuais de um operando. Operando é uma variável ou constante na qual a operação é realizada.

Todos os operadores bit a bit disponíveis no swift estão listados abaixo:

1. Operador NOT bit a bit

É representado pelo ~sinal de til e pode ser aplicado em um único operando. Isso inverte todos os bits. ou seja, muda de 1 para 0 e 0 para 1.

Se x for uma variável / constante que contém o valor binário, ou seja, 0 ou 1. A operação não bit a bit na variável x pode ser representada na tabela abaixo:

NÃO
x ~ x
0 1
1 0

Exemplo 1: operador NOT bit a bit para inteiro sem sinal

 let initalNumber:UInt8 = 1 let invertedNumber = ~initalNumber print(invertedNumber) 

Quando você executa o programa acima, a saída será:

 254

No programa acima, a instrução let initalNumber:UInt8 = 1é do tipo Unsigned int de tamanho 8 bits. Portanto, 1 em decimal pode ser representado como 00000001em binário.

O operador bit a bit not altera todo o bit de uma variável ou constante, o bit 0 é alterado para 1 e 1 para 0. Portanto, invertedNumber contém bits 11111110. Após convertê-lo em decimal, ele é representado como 254. Portanto, a instrução print(invertedNumber)gera 254 na tela.

Você também pode executar o operador bit a bit diretamente nos bits como:

Exemplo 2: operador NOT bit a bit em bits

 let initialBits: UInt8 = 0b11111111 let invertedBits = ~initialBits print(invertedBits) 

Quando você executa o programa acima, a saída será:

 0

initialBits contém um valor binário 11111111que corresponde a 255 em decimal. Para representar o número em binário, temos 0bcomo prefixo no literal. Sem o 0bprefixo, ele o tratará como um inteiro normal e você obterá um erro de estouro (UInt8 pode armazenar números de apenas 0 a 255).

Visto que usamos o operador bit a bit não, ele muda todo o 1 para 0. Portanto, a constante invertedBits contém o 00000000que é equivalente a 0 pol UInt8.

Exemplo 3: operador NOT bit a bit para inteiro assinado

 let initalNumber:Int = 1 let invertedNumber = ~initalNumber print(invertedNumber) 

Quando você executa o programa acima, a saída será:

 -2

No programa acima, 1 em decimal pode ser representado como 00000001em binário. O operador bit a bit não muda todo o bit de uma variável ou constante, o bit 0 é alterado para 1 e 1 para 0. Portanto, invertedNumber contém bits 11111110. Isso deve resultar em 254 na tela. Mas, em vez disso, retorna -2. Estranho, certo ?? Vamos explorar a seguir como isso aconteceu.

let initalNumber:Int = 1é um int assinado que pode conter inteiros positivos e negativos. É por isso que quando aplicamos o operador not para um inteiro com sinal, o binário retornado também pode representar um número negativo.

Como o compilador interpretou -2 como 11111110 binário?

O compilador usou o complemento de Dois para representar inteiros. Para obter a notação negativa do complemento de dois de um inteiro, primeiro você deve escrever o número em binário, depois inverter os dígitos e adicionar um ao resultado.

Passos para descobrir o complemento de -2 de Dois :

  1. Escreva 2 na forma binária: 00000010
  2. Inverta os dígitos. 0 torna-se 1 e 1 torna-se 0:11111101
  3. Adicionar 1: 11111110

É assim que o compilador interpreta o número binário 1111110como -2decimal. Mas, há uma pequena reviravolta que o compilador fez que não percebemos. Ele também inferiu o tipo de invertedNumber como Int8tipo.

Para entender isso, vamos ver um exemplo abaixo:

 print(Int8(bitPattern: 0b11111110)) print(0b11111110)

Quando você executa o programa acima, a saída será:

 -2 254

No exemplo acima, o compilador tratou o número binário para -2 em decimal apenas para o número inteiro assinado de 8 bits. Portanto, a instrução print(Int8(bitPattern: 0b11111110))gera -2 na tela.

Mas para o tipo inteiro normal cujo tamanho é 32/64 bits e pode conter valores grandes, ele interpreta o valor como 254. Portanto, a instrução print(0b11111110)exibe 254 na tela.

2. Operador E bit a bit

É representado por &e pode ser aplicado em dois operandos. O operador AND compara dois bits e retorna 1 se ambos os bits forem 1; caso contrário, retorna 0.

Se x e y são variáveis ​​/ constantes que mantém o valor binário, ou seja, 0 ou 1. A operação AND bit a bit em x e y pode ser representada na tabela abaixo:

E
x y x e y
0 0 0
0 1 0
1 1 1
1 0 0

Exemplo 5: operação AND bit a bit

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits & yBits print("Binary:",String(result, radix: 2)) print(result)

Quando você executa o programa acima, a saída será:

 Binário: 10000011 131 

No programa acima, a instrução let result = xBits & yBitscombina os bits de dois operandos xBits e yBits. Ele retorna 1 se ambos os bits forem 1, caso contrário, ele retorna 0.

String(value , radix: )o inicializador é usado para representar o número em diferentes sistemas numéricos. Se fornecermos o valor de raiz 2. Ele converte o número para o sistema numérico binário. Da mesma forma, podemos usar 16 para hexadecimal e 10 para decimal.

A declaração print("Binary:",String(result, radix: 2))gera Binário: 10000011 na tela. 10000011equivale a 131 em decimal, a instrução print(result)gera 131 no console.

3. Operador OR bit a bit

É representado como |e pode ser aplicado em dois operandos. O operador OR bit a bit compara dois bits e gera um resultado de 1 se uma ou mais de suas entradas são 1, caso contrário, 0.

Se x e y são variáveis ​​/ constantes que mantêm o valor binário, ou seja, 0 ou 1. A operação OR bit a bit em x e y pode ser representada na tabela abaixo:

OU
x y x | y
0 0 0
0 1 1
1 1 1
1 0 1

Exemplo 6: operação OR bit a bit

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits | yBits print("Binary:", String(result, radix: 2)) print(result) 

Quando você executa o programa acima, a saída será:

 Binário: 11111111 255 

No programa acima, a instrução let result = xBits | yBitscombina os bits de duas constantes xBits e yBits. Ele retorna 1 se qualquer um dos bits for 1, caso contrário, ele retorna 0.

A instrução print("Binary:",String(result, radix: 2))gera Binary: 11111111 na tela. Uma vez que, 11111111é equivalente a 255em decimal, a instrução print(result)gera 255 na tela.

4. Operador XOR bit a bit

É representado como ^e pode ser aplicado em dois operandos. O operador XOR compara dois bits e gera um resultado de 1 se exatamente uma de suas entradas for 1, caso contrário, ele retorna 0.

Se x e y são variáveis ​​/ constantes que mantêm o valor binário, ou seja, 0 ou 1. A operação Bitwise XOR em x e y pode ser representada na tabela abaixo:

XOR
x y x y
0 0 0
0 1 1
1 1 0
1 0 1

Exemplo 7: operação XOR bit a bit

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits yBits print("Binary:", String(result, radix: 2)) print(result) 

Quando você executa o programa acima, a saída será:

 Binário: 1111100 124 

No programa acima, a instrução let result = xBits yBitscombina os bits de duas constantes xBits e yBits. Retorna 1 se exatamente um dos bits for 1, caso contrário, retorna 0.

A instrução print("Binary:",String(result, radix: 2))gera Binário: 1111100 (equivalente a 01111100) na tela. Uma vez que, 1111100é equivalente a 124em decimal, a instrução print(result)gera 124 na tela.

5. Operador de mudança bit a bit

Esses operadores são usados ​​para mover todos os bits em um número para a esquerda ou para a direita por um certo número de casas e podem ser aplicados em um único operando. É representado como <<ou >>.

Existem dois tipos de operadores de turno:

Operador de deslocamento à esquerda bit a bit

  • Denotado como <<
  • Isso faz com que os bits sejam deslocados para a esquerda, especificada pelo número seguido por <<.
  • As posições de bit que foram liberadas pela operação de deslocamento são preenchidas com zeros.
  • Deslocar os bits de um inteiro para a esquerda em uma posição duplica seu valor

Exemplo 8: operador de deslocamento à esquerda bit a bit

 let someBits:UInt8 = 0b11000100 print(someBits << 1) 

Quando você executa o programa acima, a saída será:

 136

No programa acima, usamos o operador de deslocamento à esquerda. Usar <<1 significa deslocar o bit em 1 para a esquerda. Os dígitos são deslocados para a esquerda em uma posição e o último dígito à direita é preenchido com um zero.

Você também pode ver que o dígito que foi deslocado " do lado esquerdo " foi perdido. Não volta a dobrar da direita. Deslocá-lo um bit para a esquerda remove o 1 do binário e adiciona 0 à direita para preencher o valor deslocado, assim como o restante dos outros bits são deslocados para a posição esquerda em 1.

Isso retorna o 10001000que é equivalente a 136em UInt8. Portanto, a print(someBits << 1)instrução gera 136 na tela.

Operador de deslocamento à direita bit a bit

  • Denotado como >>
  • Isso faz com que os bits sejam deslocados para a direita pelo número seguido por >>
  • Para números sem sinal, as posições dos bits que foram vagadas pela operação de deslocamento são preenchidas com zeros.
  • Para números com sinal (números que também podem ser negativos), o bit de sinal é usado para preencher as posições de bit vagas. Em outras palavras, se o número for positivo, 0 é usado, e se o número for negativo, 1 é usado.
  • Deslocá-lo para a direita em uma posição reduz seu valor à metade.

Exemplo 9: operador de deslocamento à direita bit a bit para inteiro não assinado

 let someBits: UInt8 = 4 print(someBits>> 1) 

Quando você executa o programa acima, a saída será:

 2

No programa acima, usamos o operador de deslocamento para a direita em um inteiro sem sinal. Usar >>1 significa deslocar o bit em 1 para a direita. As posições de bit que foram liberadas pela operação de deslocamento são sempre preenchidas com zeros em um inteiro sem sinal.

Uma vez que 4 é representado como 00000100em binário. Deslocando-o um bit para a direita, retorna o 00000010que é equivalente a 2em UInt8. Portanto, a print(someBits>> 1)instrução gera 2 na tela.

Exemplo 10: operador de deslocamento à direita bit a bit para inteiro com sinal

 let someBits:Int = -4 print(someBits>> 1) 

Quando você executa o programa acima, a saída será:

 -2

No programa acima, usamos o operador de deslocamento para a direita em um inteiro sem sinal. Ao contrário dos números positivos, usando >>para números negativos, 1 é usado para preencher o lugar vago, em vez de 0.

Uma vez que, -4é representado como 11111100em binário. Deslocando-o um bit para a direita e colocando 1 na posição vaga, retorna o 11111110que é equivalente a -2for Int8type. Portanto, a print(someBits>> 1)instrução gera -2 na tela.

Artigos interessantes...