Baixe o app para aproveitar ainda mais
Prévia do material em texto
O MANIPULAÇÃO DE BITS OBJETIVOS Entender o conceito da manipulação de bits. Poder usar os operadores bit a bit. Poder usar a classe BitArray para executar a manipulação de bits. Apêndice O Manipulação de Bits O-171 O.1 Introdução Neste apêndice apresentaremos uma discussão extensa sobre a manipulação de bits e os operadores bit a bit que a permitem. Também discutiremos a classe BitArray, por meio da qual é possível criar objetos úteis para manipular conjuntos de bits. O.2 A manipulação de bits e os operadores bit a bit O C# fornece capacidades extensas de manipulação de bits para os programadores que precisam trabalhar no nível de “bits e bytes”. Os sistemas operacionais, o software de equipamentos de teste, o software de rede e muitos outros tipos de aplica- tivos exigem que os programadores se comuniquem “diretamente com o hardware”. Nesta e na próxima seção discutiremos as capacidades de manipulação do C#. Após apresentar os operadores bit a bit de C#, demonstraremos o uso dos operadores em exemplos de código vivo. Os computadores representam os dados internamente como seqüências de bits. As ALUs (Arithmetic Logic Units — unidades lógico-aritméticas), as CPUs (Central Processing Units — unidades de processamento central) e outros elemen- tos de um computador processam os dados como bits ou grupos de bits. Cada bit pode assumir o valor 0 ou 1. Em todos os sistemas, uma seqüência de oito bits forma um byte — a unidade padrão de armazenamento de uma variável do tipo byte. Os outros tipos de dados exigem números maiores de bytes para o armazenamento. Os operadores bit a bit manipulam os bits de operandos inteiros (ou seja, sbyte, byte, char, short, ushort, int, uint, long e ulong). Observe que a discussão sobre os operadores bit a bit desta seção ilustra as representações binárias dos operandos intei- ros. Para obter uma explicação detalhada do sistema de numeração binário (também chamado base 2) consulte o Apêndice B. Os operadores E bit a bit (&), OU bit a bit inclusivo (|) e OU bit a bit exclusivo (^) operam de modo semelhante aos seus equivalentes lógicos, exceto que as versões de bit a bit operam no nível de bits. O operador E bit a bit confi gura cada bit do resultado como 1, se o bit correspondente de ambos os operandos for 1 (Figura O.2). O operador OU bit a bit inclusivo confi gura cada bit do resultado como 1, se o bit correspondente de um ou ambos os operadores for 1 (Figura O.3). O opera- dor OU bit a bit exclusivo confi gura cada bit do resultado como 1, se o bit correspondente exatamente de um operando for 1 (Figura O.4). O OU exclusivo também é conhecido como XOR. O operador de deslocamento à esquerda (<<) desloca os bits de seu operando esquerdo para a esquerda pelo número de bits especifi cado em seu operando direito. O operador de deslocamento à direita (>>) desloca os bits de seu operando esquerdo para a direita pelo número de bits especifi cados em seu operando direito. Se o operando esquerdo for negativo, os 1s são deslocados a partir da esquerda, mas se o operando for positivo, os 0s são deslocados a partir da esquerda. O operador bit a bit de complemento (~) confi gura todos os bits 0 de seu operando como 1 e todos os bits 1 como 0 no resultado; esse processo às vezes é chamado de “tomar o complemento de um do valor”. Uma discussão detalhada sobre cada operador bit a bit virá nos próximos exemplos. Os operadores bit a bit e suas funções estão resumidos na Figura O.1. Ao usar os operadores bit a bit, é bom exibir os valores em suas representações binárias para ilustrar os efeitos desses operadores. Na Figura O.5, os inteiros são exibidos em suas representações binárias como grupos de oito bits cada um. O método GetBits (linhas 67 a 91) da classe PrintBits usa o operador E bit a bit (linha 79) para combinar a variável num- ber com a variável displayMask. Quase sempre, o operador E bit a bit é usado com um operando de máscara — um valor inteiro com bits específi cos confi gurados como 1. As máscaras ocultam alguns bits em um valor e selecionam outros bits. GetBits atribui à variável de máscara displayMask o valor 1 << 31 (10000000 00000000 00000000 00000000). Resumo O.1 Introdução O.2 A manipulação de bits e os operadores bit a bit O.3 A classe BitArray Resumo Terminologia C# — Como ProgramarO-172 O operador de deslocamento à esquerda desloca o valor 1 do bit de ordem inferior (mais à direita) para o bit de ordem superior (mais à esquerda) em displayMask e preenche os bits 0 a partir da direita. Como o segundo operador é 31, 31 bits (cada um é 0) são preenchidos a partir da direita. A palavra “preencher” nesse contexto signifi ca que incluímos um bit no lado direito e excluímos um no lado esquerdo. Toda vez que incluímos um 0 no lado direito, removemos o bit no lado esquerdo. A instrução da linha 79 determina se um 1 ou um 0 deve ser anexado à StringBuilder output para o bit mais à es- querda da variável number. Nesse exemplo vamos assumir que number contém 11111 (00000000 00000000 00101011 & E bit a bit Cada bit do resultado é confi gurado como 1 se os bits correspondentes dos dois operandos forem ambos 1. Caso contrário, o bit é confi gurado como 0. | OU bit a bit inclusivo Cada bit do resultado é confi gurado como 1 se pelo menos um dos bits correspondentes dos dois operandos for 1. Caso contrário, o bit é confi gurado como 0. ^ OU bit a bit exclusivo Cada bit do resultado é confi gurado como 1 se exatamente um dos bits correspondentes dos dois operandos for 1. Caso contrário, o bit é confi gurado como 0. << deslocamento à esquerda Desloca os bits do primeiro operando à esquerda pelo número de bits especifi cado pelo segundo operando; preenche a partir da direita com bits 0. >> deslocamento à direita Desloca os bits do primeiro operando à direita pelo número de bits especifi cado pelo segundo operando. Se o primeiro operando for negativo, 1s são deslocados a partir da esquerda; caso contrário, 0s são deslocados a partir da esquerda. ~ complemento Todos os bits 0 são confi gurados como 1, e todos os bits 1 são confi gurados como 0. Figura O.1 Operadores de bit a bit. Operador Nome Descrição Figura O.2 Resultados da combinação entre dois bits com o operador E bit a bit (&). 0 0 0 1 0 0 0 1 0 1 1 1 Bit 1 Bit 2 Bit 1 & Bit 2 Figura O.3 Resultados da combinação entre dois bits com o operador OU bit a bit inclusivo (|). 0 0 0 1 0 1 0 1 1 1 1 1 Bit 1 Bit 2 Bit 1 | Bit 2 Bit 1 Bit 2 Bit 1 ^ Bit 2 0 0 0 1 0 1 0 1 1 1 1 0 Figura O.4 Resultados da combinação entre dois bits com o operador OU bit a bit exclusivo (^). Apêndice O Manipulação de Bits O-173 01100111). Quando number e displayMask são combinados usando &, todos os bits (exceto o bit de ordem superior da variável) number têm uma “máscara” (são ocultos), porque qualquer bit “E” 0 resulta em 0. Se o bit mais à esquerda é 0, number & displayMask é avaliado como 0 e 0 é anexado; caso contrário, 1 é anexado. Em seguida, a linha 83 muda a variável val um bit com a expressão number << = 1 (isso é equivalente a number = number << 1). Essas etapas são repetidas para cada bit da variável number. No fi nal do método GetBits, a linha 89 converte StringBuilder em uma string e a retorna do método. Figura O.5 Exibindo a representação de bits de um inteiro. (Parte 1 de 2.) 1 // Fig. O.5: PrintBits.cs 2 // Imprimindo os bits que constituem um inteiro. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 using System.Text; 11 12 13 // exibe a representação de bits da entrada do usuário 14 public class PrintBits : System.Windows.Forms.Form 15 { 16 private System.Windows.Forms.Label promptLabel; 17 private System.Windows.Forms.Label viewLabel; 18 19 // para a entradade usuário 20 private System.Windows.Forms.TextBox inputTextBox; 21 22 // a representação de bits é exibida aqui 23 private System.Windows.Forms.Label displayLabel; 24 25 private System.ComponentModel.Container components = null; 26 27 // construtor padrão 28 public PrintBits() 29 { 30 InitializeComponent(); 31 } 32 33 // código gerado pelo Visual Studio .NET 34 35 [STAThread] 36 static void Main() 37 { 38 Application.Run( new PrintBits() ); 39 } 40 41 // processa o inteiro quando o usuário pressiona Enter 42 private void inputTextBox_KeyDown( 43 object sender, System.Windows.Forms.KeyEventArgs e ) 44 { 45 // se o usuário pressionou Enter 46 if ( e.KeyCode == Keys.Enter ) 47 { 48 // testa se o usuário inseriu um inteiro 49 try C# — Como ProgramarO-174 50 { 51 displayLabel.Text = GetBits( 52 Convert.ToInt32( inputTextBox.Text ) ); 53 } 54 55 // se o valor não é um inteiro, a exceção é declarada 56 catch ( FormatException ) 57 { 58 MessageBox.Show( “Please Enter an Integer”, 59 “Error”, MessageBoxButtons.OK, 60 MessageBoxIcon.Error ); 61 } 62 } 63 64 } // fi m do método inputTextBox_KeyDown 65 66 // converte o inteiro em sua representação de bits 67 public string GetBits( int number ) 68 { 69 int displayMask = 1 << 31; 70 71 StringBuilder output = new StringBuilder(); 72 73 // obtém cada bit, inclui espaço a cada 8 bits 74 // para formatação da exibição 75 for ( int c = 1; c <= 32; c++ ) 76 { 77 // anexa 0 ou 1 dependendo do resultado da máscara 78 output.Append( 79 ( number & displayMask ) == 0 ? “0” : “1” ); 80 81 // mudança à esquerda para que a máscara encontre o bit do 82 // próximo dígito durante a próxima interação do laço 83 number <<= 1; 84 85 if ( c % 8 == 0 ) 86 output.Append( “ ” ); 87 } 88 89 return output.ToString(); 90 91 } // fi m do método GetBits 92 93 } // fi m da classe PrintBits Figura O.5 Exibindo a representação de bits de um inteiro. (Parte 2 de 2.) Erro de programação comum O.1 O uso do operador E lógico (&&) no lugar do operador E bit a bit (&) é um erro de programação comum. Erro de programação comum O.2 O uso do operador OU lógico (||) no lugar do operador OU bit a bit inclusivo (|) é um erro comum de programação. Apêndice O Manipulação de Bits O-175 O programa da Figura O.6 demonstra os operadores E bit a bit, OU bit a bit inclusivo, OU bit a bit exclusivo e comple- mento bit a bit. O programa usa o método GetBits, o qual retorna uma string contendo a representação em bits de seu argumento inteiro. Os usuários fornecem valores em TextBoxes e pressionam o botão correspondente à operação que eles gostariam de testar. O programa exibe o resultado nas representações inteiras e de bits. Figura O.6 Demonstrando os operadores E bit a bit, OU bit a bit inclusivo, OU bit a bit exclusivo e complemento bit a bit. (Parte 1 de 3.) 1 // Fig. O.6: BitOperations.cs 2 // Uma classe que demonstra diversas operações de bits 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 using System.Text; 11 12 // permite que o usuário teste os operadores de bits 13 public class BitOperations : System.Windows.Forms.Form 14 { 15 private System.Windows.Forms.Label promptLabel; 16 private System.Windows.Forms.Label representationLabel; 17 private System.Windows.Forms.Label value1Label; 18 private System.Windows.Forms.Label value2Label; 19 private System.Windows.Forms.Label resultLabel; 20 21 // exibe as representações de bits 22 private System.Windows.Forms.Label bit1Label; 23 private System.Windows.Forms.Label bit2Label; 24 private System.Windows.Forms.Label resultBitLabel; 25 26 // permite que o usuário execute as operações de bits 27 private System.Windows.Forms.Button andButton; 28 private System.Windows.Forms.Button inclusiveOrButton; 29 private System.Windows.Forms.Button exclusiveOrButton; 30 private System.Windows.Forms.Button complementButton; 31 32 // o usuário fornece dois inteiros 33 private System.Windows.Forms.TextBox bit1TextBox; 34 private System.Windows.Forms.TextBox bit2TextBox; 35 36 private System.Windows.Forms.TextBox resultTextBox; 37 38 private int value1, value2; 39 40 private System.ComponentModel.Container components = null; 41 42 // construtor padrão 43 public BitOperations() 44 { 45 InitializeComponent(); 46 } 47 48 // código gerado pelo Visual Studio .NET 49 50 [STAThread] 51 static void Main() 52 { C# — Como ProgramarO-176 53 Application.Run( new BitOperations() ); 54 } 55 56 // E 57 private void andButton_Click( 58 object sender, System.EventArgs e ) 59 { 60 SetFields(); 61 62 // atualiza resultTextBox 63 resultTextBox.Text = 64 string.Format( “{0}”, value1 & value2 ); 65 66 resultBitLabel.Text = GetBits( value1 & value2 ); 67 } 68 69 // OU inclusivo 70 private void inclusiveOrButton_Click( 71 object sender, System.EventArgs e ) 72 { 73 SetFields(); 74 75 // atualiza resultTextBox 76 resultTextBox.Text = 77 string.Format( “{0}”, value1 | value2 ); 78 resultBitLabel.Text = GetBits( value1 | value2 ); 79 } 80 81 //OU exclusivo 82 private void exclusiveOrButton_Click( 83 object sender, System.EventArgs e ) 84 { 85 SetFields(); 86 87 // atualiza resultTextBox 88 resultTextBox.Text = 89 string.Format( “{0}”, value1 ^ value2 ); 90 resultBitLabel.Text = GetBits( value1 ^ value2 ); 91 } 92 93 // complemento do primeiro inteiro 94 private void complementButton_Click( 95 object sender, System.EventArgs e ) 96 { 97 value1 = Convert.ToInt32( bit1TextBox.Text ); 98 bit1Label.Text = GetBits( value1 ); 99 100 // atualiza resultTextBox 101 resultTextBox.Text = string.Format( “{0}”, ~value1 ); 102 resultBitLabel.Text = GetBits( ~value1 ); 103 } 104 105 // converte o inteiro em sua representação de bits 106 private string GetBits( int number ) 107 { 108 int displayMask = 1 << 31; 109 Figura O.6 Demonstrando os operadores E bit a bit, OU bit a bit inclusivo, OU bit a bit exclusivo e complemento bit a bit. (Parte 2 de 3.) Apêndice O Manipulação de Bits O-177 110 StringBuilder output = new StringBuilder(); 111 112 // obtém cada bit, inclui espaço a cada 8 bits 113 // para a formatação da exibição 114 for ( int c = 1; c <= 32; c++ ) 115 { 116 // anexa 0 ou 1 dependendo do resultado da máscara 117 output.Append( 118 ( number & displayMask ) == 0 ? “0” : “1” ); 119 120 // muda à esquerda para que a máscara encontre o bit do 121 // próximo dígito da próxima iteração do laço 122 number <<= 1; 123 124 if ( c % 8 == 0 ) 125 output.Append( “ ” ); 126 } 127 128 return output.ToString(); 129 130 } // fi m do método GetBits 131 132 // defi ne os campos do formulário 133 private void SetFields() 134 { 135 // recupera os valores de entrada 136 value1 = Convert.ToInt32( bit1TextBox.Text ); 137 value2 = Convert.ToInt32( bit2TextBox.Text ); 138 139 // defi ne os rótulos para exibir as representações de bit dos inteiros 140 bit1Label.Text = GetBits( value1 ); 141 bit2Label.Text = GetBits( value2 ); 142 } 143 144 } // fi m da classe BitOperations Figura O.6 Demonstrando os operadores E bit a bit, OU bit a bit inclusivo, OU bit a bit exclusivo e complemento bit a bit. (Parte 3 de 3.) C# — Como ProgramarO-178 A primeira janela de saída da Figura 0.6 mostra os resultados da combinação entre o valor 17 e 20 usando o operador E bit a bit (&); o resultado é 16. A segunda janela de saídamostra os resultados da combinação entre o valor 17 e 20 usando o operador OU bit a bit; o resultado é 21. A terceira saída mostra os resultados da combinação entre o valor 17 e 20 usando o ope- rador OU exclusivo; o resultado é 5. A quarta janela de saída mostra os resultados de tomar o complemento de um do valor 17; o resultado é -18. O programa da Figura O.7 demonstra o uso do operador de deslocamento à esquerda (<<) e o operador de desloca- mento à direita (>>). O método GetBits retorna uma string contendo a representação de bits de um valor inteiro passado para ele como um argumento. Quando os usuários fornecem um inteiro em uma TextBox e pressionam Enter, o programa exibe a representação de bits do inteiro especifi cado em um Label. Figura O.7 Usando os operadores de deslocamento de bits. (Parte 1 de 3.) 1 // Fig. O.7: Deslocamento de bits.cs 2 // Demonstra os operadores de deslocamento de bits. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 using System.Text; 11 12 // desloca os bits à direita ou à esquerda 13 public class Deslocamento de bits : System.Windows.Forms.Form 14 { 15 private System.Windows.Forms.Label inputLabel; 16 17 // aceita a entrada de usuário 18 private System.Windows.Forms.TextBox inputTextBox; 19 20 // exibe o inteiro em bits 21 private System.Windows.Forms.Label displayLabel; 22 private System.Windows.Forms.Button rightButton; 23 private System.Windows.Forms.Button leftButton; 24 25 private System.ComponentModel.Container components = null; 26 27 // construtor padrão 28 public Deslocamento de bits() 29 { 30 InitializeComponent(); 31 } 32 33 // código gerado pelo Visual Studio .NET 34 35 [STAThread] 36 static void Main() 37 { 38 Application.Run( new Deslocamento de bits() ); 39 } 40 41 // processa a entrada de usuário 42 private void inputTextBox_KeyDown( 43 object sender, System.Windows.Forms.KeyEventArgs e ) 44 { 45 if ( e.KeyCode == Keys.Enter ) 46 displayLabel.Text = Apêndice O Manipulação de Bits O-179 47 GetBits( Convert.ToInt32( inputTextBox.Text ) ); 48 } 49 50 // realiza o deslocamento à esquerda 51 private void leftButton_Click( 52 object sender, System.EventArgs e ) 53 { 54 // recupera a entrada de usuário 55 int number = Convert.ToInt32( inputTextBox.Text ); 56 57 // realiza a operação de deslocamento à esquerda 58 number <<= 1; 59 60 // converte para inteiro e exibe na caixa de texto 61 inputTextBox.Text = number.ToString(); 62 63 // exibe os bits no rótulo 64 displayLabel.Text = GetBits( number ); 65 } 66 67 // faz o deslocamento à direita 68 private void rightButton_Click( 69 object sender, System.EventArgs e ) 70 { 71 // recupera a entrada de usuário 72 int number = Convert.ToInt32( inputTextBox.Text ); 73 74 // faz a operação de deslocamento à direita 75 number >>= 1; 76 77 // converte para inteiro e exibe na caixa de texto 78 inputTextBox.Text = number.ToString(); 79 80 // exibe os bits no rótulo 81 displayLabel.Text = GetBits( number ); 82 } 83 84 // converte o inteiro em sua representação de bit 85 private string GetBits( int number ) 86 { 87 int displayMask = 1 << 31; 88 89 StringBuilder output = new StringBuilder(); 90 91 // obtém cada bit, adiciona um espaço a cada 8 bits 92 // para exibição formatada 93 for ( int c = 1; c <= 32; c++ ) 94 { 95 // anexa um 0 ou 1 dependendo do resultado da máscara 96 output.Append( 97 ( number & displayMask ) == 0 ? “0” : “1” ); 98 99 // desloca à esquerda para que a máscara encontre o bit do 100 // próximo dígito durante a próxima iteração do laço 101 number <<= 1; 102 103 if ( c % 8 == 0 ) 104 output.Append( “ ” ); Figura O.7 Usando os operadores de deslocamento de bits. (Parte 2 de 3.) C# — Como ProgramarO-180 105 } 106 107 return output.ToString(); 108 109 } // fi m do método GetBits 110 111 } // fi m da classe BitShift Figura O.7 Usando os operadores de deslocamento de bits. (Parte 3 de 3.) Cada operador de deslocamento tem seu próprio botão na GUI do aplicativo. Quando um usuário dá um clique em cada botão, os bits do inteiro são deslocados à esquerda ou à direita em um bit. TextBox e Label exibem o novo valor de inteiro e a nova representação de bits, respectivamente. O operador de deslocamento à esquerda (<<) desloca os bits de seu operando esquerdo para a esquerda pelo número de bits especifi cado em seu operando direito. Os bits mais à direita são substituídos por 0s; os 1s deslocados para fora da esquerda se perdem. As duas primeiras janelas de saída da Figura O.7 demonstram o operador de deslocamento à esquerda. Para produ- zir a saída, o usuário forneceu o valor 23 e deu um clique no botão de deslocamento à esquerda, resultando no valor 46. O operador de deslocamento à direita (>>) muda os bits de seu operando esquerdo para a direita pelo número de bits especifi cados em seu operando direito. Os 0s substituem os bits vagos no lado esquerdo se o número for positivo, e os 1s substituem os bits vagos se o número for negativo. Todos os 1s deslocados para fora da extrema direita se perdem. A terceira e a quarta janela de saída descrevem o resultado da mudança de 184 uma vez para a direita. Cada operador bit a bit (exceto o operador de complemento bit a bit) tem um operador correspondente de atribuição. A Figura O.8 descreve esses operadores de atribuição bit a bit, os quais são usados de modo semelhante aos operadores de designação aritmética apresentados no Capítulo 3. Operadores de atribuição bit a bit &= Operador de atribuição E bit a bit. |= Operador de atribuição OU bit a bit inclusivo. Figura O.8 Operadores de atribuição bit a bit. (Parte 1 de 2.) Apêndice O Manipulação de Bits O-181 O.3 A Classe BitArray A classe BitArray facilita a criação e a manipulação de conjuntos de bits, os quais são muito usados pelos programadores para representar um conjunto de fl ags booleanos. Um fl ag booleano é uma variável que registra uma determinada decisão booleana. Os BitArrays são redimensionáveis dinamicamente — mais bits podem ser incluídos depois que um objeto BitArray é criado. Isso faz com que o objeto aumente para acomodar os bits adicionais. A classe BitArray fornece diversos construtores, um dos quais aceita um int como um argumento. O int especi- fi ca o número de bits que BitArray representa. Todos eles são defi nidos inicialmente como false. O método Set de BitArray pode mudar o valor de um bit individual; ele aceita o índice do bit a ser alterado e seu novo valor bool. A classe BitArray também inclui um indexador que permite obter e confi gurar os valores individuais de bit. O indexador retorna true se o bit especifi cado estiver ligado (ou seja, o bit tiver o valor 1) e retorna false, caso contrário (ou seja, o bit tem o valor 0 ou “desligado”). O método And da classe BitArray executa um E bit a bit entre dois BitArrays e retorna o resultado de BitArray da operação. Os métodos Or e Xor executam as operações OU bit a bit inclusivo e OU bit a bit exclusivo, respectivamente. A classe BitArray também fornece uma propriedade Length, a qual retorna o número de elementos do BitArray. A Figura O.9 implementa a peneira de Erastótenes, que consiste em uma técnica para localizar números primos. Um número primo é um inteiro divisível apenas por si mesmo e por 1. A peneira de Erastótenes opera desta maneira: a) Cria um array com todos os elementos inicializados como 1 (verdadeiro). Os elementos de array com índices primos permanecem 1. Todos os outros elementos do array são eventualmente confi gurados como 0. b) Começando com o índice de array 2 (o índice 1não deve ser primo), sempre que um elemento do array é encon- trado com um valor de 1 percorre o restante do array e confi gura como 0 cada elemento cujo índice é um múltiplo do índice do elemento com o valor 1. Por exemplo, para o índice de array 2, todos os elementos após o 2 no array que são múltiplos de 2 são confi gurados como 0 (os índices 4, 6, 8, 10 etc.); para o índice de array 3, todos os elementos após 3 do array que são múltiplos de 3 são confi gurados como 0 (índices 6, 9, 12, 15 etc.) e assim por diante. No fi nal desse processo, os índices dos elementos de array que são 1 são os números primos. Em seguida, a lista de números primos pode ser exibida pela localização e impressão desses índices. Operadores de atribuição bit a bit Figura O.8 Operadores de atribuição bit a bit. (Parte 2 de 2.) ^= Operador de atribuição OU bit a bit exclusivo. <<= Operador de atribuição de deslocamento à esquerda. >>= Operador de atribuição de deslocamento à direita. Figura O.9 Peneira de Erastótenes. (Parte 1 de 3.) 1 // Fig. O.9: BitArrayTest.cs 2 // Demonstra a classe BitArray. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 11 // implementa a peneira de Erastótenes 12 public class BitArrayTest : System.Windows.Forms.Form C# — Como ProgramarO-182 13 { 14 private System.Windows.Forms.Label promptLabel; 15 16 // o usuário fornece o inteiro 17 private System.Windows.Forms.TextBox inputTextBox; 18 19 // exibe números primos 20 private System.Windows.Forms.TextBox outputTextBox; 21 22 // exibe se o inteiro da entrada é primo 23 private System.Windows.Forms.Label displayLabel; 24 25 private BitArray sieve; 26 27 private System.ComponentModel.Container components = null; 28 29 // construtor padrão 30 public BitArrayTest() 31 { 32 InitializeComponent(); 33 34 // cria o BitArray e confi gura todos os bits como verdadeiro 35 sieve = new BitArray( 1024 ); 36 sieve.SetAll( true ); 37 38 int fi nalBit = ( int ) Math.Sqrt( sieve.Length ); 39 40 // executa a operação de peneira 41 for ( int i = 2; i < fi nalBit; i++ ) 42 if ( sieve.Get( i ) ) 43 for ( int j = 2 * i; j < sieve.Length; j += i ) 44 sieve.Set( j, false ); 45 46 int counter = 0; 47 48 // exibe os números primos 49 for ( int i = 2; i < sieve.Length; i++ ) 50 if ( sieve.Get( i ) ) 51 outputTextBox.Text += i + 52 ( ++counter % 7 == 0 ? “\r\n” : “ ” ); 53 } 54 55 // código gerado pelo Visual Studio .NET 56 57 [STAThread] 58 static void Main() 59 { 60 Application.Run( new BitArrayTest() ); 61 } 62 63 private void inputTextBox_KeyDown( 64 object sender, System.Windows.Forms.KeyEventArgs e ) 65 { 66 // se o usuário pressionou Enter 67 if ( e.KeyCode == Keys.Enter ) 68 { 69 int number = Convert.ToInt32( inputTextBox.Text ); 70 Figura O.9 Peneira de Erastótenes. (Parte 2 de 3.) Apêndice O Manipulação de Bits O-183 Figura O.9 Peneira de Erastótenes. (Parte 3 de 3.) 71 // se a peneira é verdadeira no índice do inteiro 72 // fornecido pelo usuário, então o número é primo 73 if ( sieve.Get( number ) ) 74 displayLabel.Text = number + “ is a prime number”; 75 else 76 displayLabel.Text = 77 number + “ is not a prime number”; 78 } 79 } // fi m do método inputTextBox_KeyDown 80 81 } // fi m da classe BitArrayTest Usamos um BitArray para implementar o algoritmo. O programa exibe os números primos do intervalo de 1 a 1023 em uma TextBox. O programa também fornece uma TextBox na qual os usuários podem digitar qualquer número de 1 a 1023 para determinar se aquele número é primo (caso em que ele exibe uma mensagem indicando que o número é primo). A instrução da linha 35 cria um BitArray de 1024 bits. O método BitArray SetAll confi gura todos os bits como true na linha 36; em seguida, as linhas 41 a 44 determinam todos os números primos ocorridos entre 1 e 1023. O inteiro fi nalBit determina quando o algoritmo está completo. Quando o usuário insere um número e pressiona Enter, a linha 73 testa se o número da entrada é primo. Essa linha usa o método Get da classe BitArray, a qual toma um número e retorna o valor daquele bit no array. As linhas 74 e 76 imprimem uma resposta apropriada. Resumo Os computadores representam os dados internamente como seqüências de bits. Cada bit pode assumir o valor 0 ou o valor 1. Em todos os sistemas, uma seqüência de 8 bits forma um byte — a unidade de armazenamento padrão de uma variável do tipo byte. Os outros tipos de dados exigem números maiores de bytes para o armazenamento. O operador E bit a bit confi gura cada bit do resultado como 1 se os bits correspondentes em ambos os operandos for 1. O operador OU bit a bit inclusivo confi gura cada um dos bits do resultado como 1 se o bit correspondente de um operando (ou ambos) for 1. O operador OU bit a bit exclusivo confi gura cada bit do resultado como 1 se o bit correspondente em exatamente um operando for 1. O OU exclusivo também é conhecido como XOR. O operador de deslocamento à esquerda (<<) desloca os bits de seu operando esquerdo para a esquerda pelo número de bits especifi - cados em seu operando direito. C# — Como ProgramarO-184 O operador de deslocamento à direita (>>) desloca os bits de seu operando esquerdo para a direita pelo número de bits especifi cados em seu operando direito. Se o operando esquerdo for negativo, os 1s são deslocados a partir da esquerda, enquanto se o operando esquerdo for positivo, os 0s são deslocados a partir da esquerda. O operador de complemento bit a bit (~) confi gura todos os bits 0 de seu operando como 1 no resultado e confi gura todos os bits 1 como 0 no resultado; esse processo também é chamado de “tomar o complemento de um do valor”. Com freqüência, o operador E bit a bit é usado com um operando de máscara — um valor de inteiro com bits específi cos confi gurados como 1. As máscaras ocultam alguns bits de um valor e selecionam outros bits. Cada operador bit a bit (exceto o operador de complemento bit a bit) tem um operador de atribuição. A classe BitArray facilita a criação e manipulação dos conjuntos de bits, os quais são muito usados pelos programadores para representar um conjunto de fl ags booleanos. Um fl ag booleano é uma variável que registra determinada decisão booleana. Os BitArrays são redimensionados dinamicamente — mais bits podem ser adicionados depois que um BitArray é criado. Isso faz com que o objeto aumente para acomodar os bits adicionais. O método Set de BitArray pode alterar o valor de um bit individual — ele aceita o índice do bit a ser alterado e o valor bool para o qual o bit deve ser mudado. O método BitArray And executa um E bit a bit entre dois BitArrays. Ele retorna o BitArray que é o resultado da execução dessa operação. Os métodos Or e Xor executam o OU bit a bit inclusivo e OU bit a bit exclusivo, respectivamente. O método BitArray SetAll confi gura todos os bits de BitArray como true. Terminologia & (E bit a bit) &= (operador bit a bit de atribuição E) ^ (OU bit a bit exclusivo) | (OU bit a bit inclusivo) |= (operador de atribuição OU bit a bit inclusivo) ~ (operador de complemento bit a bit) << (operador de deslocamento à esquerda) <<= (operador de atribuição de deslocamento à esquerda) >> (operador de deslocamento à direita) >>= (operador de atribuição de deslocamento à direita) ALU (Arithmetic Logic Unit — unidade lógica aritmética) bit bit de ordem inferior bit de ordem superior BitArrayText.cs BitShfi t.cs byte classe BitArray complemento de um (~) conjunto de bits CPU (Central Processing Unit — unidade de processamento central) decisão booleana E bit abit (&) fl ag booleano indexador BitArray manipulação de bits máscara de bits método And da classe BitArray método Get da classe BitArray método Or da classe BitArray método Set da classe BitArray método SetAll da classe BitArray método Xor da classe BitArray nível de bits e bytes número primo operador de atribuição bit a bit E (&=) operador de atribuição de deslocamento à direita (>>=) operador de atribuição de deslocamento à esquerda (<<=) operador de atribuição OU bit a bit exclusivo (^=) operador de atribuição OU bit a bit inclusivo (|=) operador de complemento bit a bit (~) operador de deslocamento à direita (>>) operador OU bit a bit exclusivo (^) operador OU bit a bit inclusivo (|) operadores de atribuição bit a bit operadores bit a bit peneira de Erastótenes propriedade Length da classe BitArray representação binária representação de bits de um inteiro sistema de numeração base 2 sistema de numeração binário tipo de dados primitivo byte XOR (OU exclusivo)
Compartilhar