Escolar Documentos
Profissional Documentos
Cultura Documentos
MANIPULAO DE BITS
OBJETIVOS
Entender o conceito da manipulao de bits. Poder usar os operadores bit a bit. Poder usar a classe BitArray para executar a manipulao de bits.
O-171
Resumo
O.1 O.2 O.3 Introduo A manipulao de bits e os operadores bit a bit A classe BitArray
Resumo Terminologia
O.1 Introduo
Neste apndice apresentaremos uma discusso extensa sobre a manipulao de bits e os operadores bit a bit que a permitem. Tambm discutiremos a classe BitArray, por meio da qual possvel criar objetos teis para manipular conjuntos de bits.
O-172
C# Como Programar
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) so preenchidos a partir da direita. A palavra preencher nesse contexto signica que inclumos um bit no lado direito e exclumos um no lado esquerdo. Toda vez que inclumos um 0 no lado direito, removemos o bit no lado esquerdo. A instruo da linha 79 determina se um 1 ou um 0 deve ser anexado StringBuilder output para o bit mais esquerda da varivel number. Nesse exemplo vamos assumir que number contm 11111 (00000000 00000000 00101011
Nome E bit a bit OU bit a bit inclusivo OU bit a bit exclusivo deslocamento esquerda deslocamento direita
Descrio Cada bit do resultado congurado como 1 se os bits correspondentes dos dois operandos forem ambos 1. Caso contrrio, o bit congurado como 0. Cada bit do resultado congurado como 1 se pelo menos um dos bits correspondentes dos dois operandos for 1. Caso contrrio, o bit congurado como 0. Cada bit do resultado congurado como 1 se exatamente um dos bits correspondentes dos dois operandos for 1. Caso contrrio, o bit congurado como 0. Desloca os bits do primeiro operando esquerda pelo nmero de bits especicado pelo segundo operando; preenche a partir da direita com bits 0. Desloca os bits do primeiro operando direita pelo nmero de bits especicado pelo segundo operando. Se o primeiro operando for negativo, 1s so deslocados a partir da esquerda; caso contrrio, 0s so deslocados a partir da esquerda. Todos os bits 0 so congurados como 1, e todos os bits 1 so congurados como 0.
complemento
Bit 1 0 1 0 1
Bit 2 0 0 1 1
Figura O.2 Resultados da combinao entre dois bits com o operador E bit a bit (&).
Bit 1 0 1 0 1
Bit 2 0 0 1 1
Bit 1 | Bit 2 0 1 1 1
Figura O.3 Resultados da combinao entre dois bits com o operador OU bit a bit inclusivo (|).
Bit 1 0 1 0 1
Bit 2 0 0 1 1
Bit 1 ^ Bit 2 0 1 1 0
Figura O.4 Resultados da combinao entre dois bits com o operador OU bit a bit exclusivo (^).
O-173
01100111). Quando number e displayMask so combinados usando &, todos os bits (exceto o bit de ordem superior da varivel) number tm uma mscara (so ocultos), porque qualquer bit E 0 resulta em 0. Se o bit mais esquerda 0, number & displayMask avaliado como 0 e 0 anexado; caso contrrio, 1 anexado. Em seguida, a linha 83 muda a varivel val um bit com a expresso number << = 1 (isso equivalente a number = number << 1). Essas etapas so repetidas para cada bit da varivel number. No nal do mtodo GetBits, a linha 89 converte StringBuilder em uma string e a retorna do mtodo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
// Fig. O.5: PrintBits.cs // Imprimindo os bits que constituem um inteiro. using using using using using using using System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data; System.Text;
// exibe a representao de bits da entrada do usurio public class PrintBits : System.Windows.Forms.Form { private System.Windows.Forms.Label promptLabel; private System.Windows.Forms.Label viewLabel; // para a entrada de usurio private System.Windows.Forms.TextBox inputTextBox; // a representao de bits exibida aqui private System.Windows.Forms.Label displayLabel; private System.ComponentModel.Container components = null; // construtor padro public PrintBits() { InitializeComponent(); } // cdigo gerado pelo Visual Studio .NET [STAThread] static void Main() { Application.Run( new PrintBits() ); } // processa o inteiro quando o usurio pressiona Enter private void inputTextBox_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e ) { // se o usurio pressionou Enter if ( e.KeyCode == Keys.Enter ) { // testa se o usurio inseriu um inteiro try
O-174
C# Como Programar
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
{ displayLabel.Text = GetBits( Convert.ToInt32( inputTextBox.Text ) ); } // se o valor no um inteiro, a exceo declarada catch ( FormatException ) { MessageBox.Show( Please Enter an Integer, Error, MessageBoxButtons.OK, MessageBoxIcon.Error ); } } } // m do mtodo inputTextBox_KeyDown // converte o inteiro em sua representao de bits public string GetBits( int number ) { int displayMask = 1 << 31; StringBuilder output = new StringBuilder(); // obtm cada bit, inclui espao a cada 8 bits // para formatao da exibio for ( int c = 1; c <= 32; c++ ) { // anexa 0 ou 1 dependendo do resultado da mscara output.Append( ( number & displayMask ) == 0 ? 0 : 1 ); // mudana esquerda para que a mscara encontre o bit do // prximo dgito durante a prxima interao do lao number <<= 1; if ( c % 8 == 0 ) output.Append( ); } return output.ToString(); } // m do mtodo GetBits } // m da classe PrintBits
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 complemento bit a bit. O programa usa o mtodo GetBits, o qual retorna uma string contendo a representao em bits de seu argumento inteiro. Os usurios fornecem valores em TextBoxes e pressionam o boto correspondente operao que eles gostariam de testar. O programa exibe o resultado nas representaes inteiras e de bits.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
// Fig. O.6: BitOperations.cs // Uma classe que demonstra diversas operaes de bits using using using using using using using System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data; System.Text;
// permite que o usurio teste os operadores de bits public class BitOperations : System.Windows.Forms.Form { private System.Windows.Forms.Label promptLabel; private System.Windows.Forms.Label representationLabel; private System.Windows.Forms.Label value1Label; private System.Windows.Forms.Label value2Label; private System.Windows.Forms.Label resultLabel; // exibe as representaes de bits private System.Windows.Forms.Label bit1Label; private System.Windows.Forms.Label bit2Label; private System.Windows.Forms.Label resultBitLabel; // permite que o usurio execute as private System.Windows.Forms.Button private System.Windows.Forms.Button private System.Windows.Forms.Button private System.Windows.Forms.Button operaes de bits andButton; inclusiveOrButton; exclusiveOrButton; complementButton;
// o usurio fornece dois inteiros private System.Windows.Forms.TextBox bit1TextBox; private System.Windows.Forms.TextBox bit2TextBox; private System.Windows.Forms.TextBox resultTextBox; private int value1, value2; private System.ComponentModel.Container components = null; // construtor padro public BitOperations() { InitializeComponent(); } // cdigo gerado pelo Visual Studio .NET [STAThread] static void Main() {
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.)
O-176
C# Como Programar
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
Application.Run( new BitOperations() ); } // E private void andButton_Click( object sender, System.EventArgs e ) { SetFields(); // atualiza resultTextBox resultTextBox.Text = string.Format( {0}, value1 & value2 ); resultBitLabel.Text = GetBits( value1 & value2 ); } // OU inclusivo private void inclusiveOrButton_Click( object sender, System.EventArgs e ) { SetFields(); // atualiza resultTextBox resultTextBox.Text = string.Format( {0}, value1 | value2 ); resultBitLabel.Text = GetBits( value1 | value2 ); } //OU exclusivo private void exclusiveOrButton_Click( object sender, System.EventArgs e ) { SetFields(); // atualiza resultTextBox resultTextBox.Text = string.Format( {0}, value1 ^ value2 ); resultBitLabel.Text = GetBits( value1 ^ value2 ); } // complemento do primeiro inteiro private void complementButton_Click( object sender, System.EventArgs e ) { value1 = Convert.ToInt32( bit1TextBox.Text ); bit1Label.Text = GetBits( value1 ); // atualiza resultTextBox resultTextBox.Text = string.Format( {0}, ~value1 ); resultBitLabel.Text = GetBits( ~value1 ); } // converte o inteiro em sua representao de bits private string GetBits( int number ) { int displayMask = 1 << 31;
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.)
O-177
110 StringBuilder output = new StringBuilder(); 111 // obtm cada bit, inclui espao a cada 8 bits 112 113 // para a formatao da exibio 114 for ( int c = 1; c <= 32; c++ ) 115 { 116 // anexa 0 ou 1 dependendo do resultado da mscara 117 output.Append( 118 ( number & displayMask ) == 0 ? 0 : 1 ); 119 120 // muda esquerda para que a mscara encontre o bit do 121 // prximo dgito da prxima iterao do lao 122 number <<= 1; 123 if ( c % 8 == 0 ) 124 125 output.Append( ); 126 } 127 return output.ToString(); 128 129 } // m do mtodo GetBits 130 131 // dene os campos do formulrio 132 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 // dene os rtulos para exibir as representaes de bit dos inteiros 140 bit1Label.Text = GetBits( value1 ); 141 bit2Label.Text = GetBits( value2 ); 142 } 143 144 } // 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.)
O-178
C# Como Programar
A primeira janela de sada da Figura 0.6 mostra os resultados da combinao entre o valor 17 e 20 usando o operador E bit a bit (&); o resultado 16. A segunda janela de sada mostra os resultados da combinao entre o valor 17 e 20 usando o operador OU bit a bit; o resultado 21. A terceira sada mostra os resultados da combinao entre o valor 17 e 20 usando o operador OU exclusivo; o resultado 5. A quarta janela de sada 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 deslocamento direita (>>). O mtodo GetBits retorna uma string contendo a representao de bits de um valor inteiro passado para ele como um argumento. Quando os usurios fornecem um inteiro em uma TextBox e pressionam Enter, o programa exibe a representao de bits do inteiro especicado em um Label.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
// Fig. O.7: Deslocamento de bits.cs // Demonstra os operadores de deslocamento de bits. using using using using using using using System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data; System.Text;
// desloca os bits direita ou esquerda public class Deslocamento de bits : System.Windows.Forms.Form { private System.Windows.Forms.Label inputLabel; // aceita a entrada de usurio private System.Windows.Forms.TextBox inputTextBox; // exibe o inteiro em bits private System.Windows.Forms.Label displayLabel; private System.Windows.Forms.Button rightButton; private System.Windows.Forms.Button leftButton; private System.ComponentModel.Container components = null; // construtor padro public Deslocamento de bits() { InitializeComponent(); } // cdigo gerado pelo Visual Studio .NET [STAThread] static void Main() { Application.Run( new Deslocamento de bits() ); } // processa a entrada de usurio private void inputTextBox_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e ) { if ( e.KeyCode == Keys.Enter ) displayLabel.Text =
O-179
GetBits( Convert.ToInt32( inputTextBox.Text ) ); } // realiza o deslocamento esquerda private void leftButton_Click( object sender, System.EventArgs e ) { // recupera a entrada de usurio int number = Convert.ToInt32( inputTextBox.Text ); // realiza a operao de deslocamento esquerda number <<= 1; // converte para inteiro e exibe na caixa de texto inputTextBox.Text = number.ToString(); // exibe os bits no rtulo displayLabel.Text = GetBits( number ); } // faz o deslocamento direita private void rightButton_Click( object sender, System.EventArgs e ) { // recupera a entrada de usurio int number = Convert.ToInt32( inputTextBox.Text ); // faz a operao de deslocamento direita number >>= 1; // converte para inteiro e exibe na caixa de texto inputTextBox.Text = number.ToString(); // exibe os bits no rtulo displayLabel.Text = GetBits( number ); } // converte o inteiro em sua representao de bit private string GetBits( int number ) { int displayMask = 1 << 31; StringBuilder output = new StringBuilder(); // obtm cada bit, adiciona um espao a cada 8 bits // para exibio formatada for ( int c = 1; c <= 32; c++ ) { // anexa um 0 ou 1 dependendo do resultado da mscara output.Append( ( number & displayMask ) == 0 ? 0 : 1 ); // desloca esquerda para que a mscara encontre o bit do // prximo dgito durante a prxima iterao do lao number <<= 1; if ( c % 8 == 0 ) output.Append( );
O-180
C# Como Programar
105 } 106 107 return output.ToString(); 108 109 } // m do mtodo GetBits 110 111 } // m da classe BitShift
Cada operador de deslocamento tem seu prprio boto na GUI do aplicativo. Quando um usurio d um clique em cada boto, os bits do inteiro so deslocados esquerda ou direita em um bit. TextBox e Label exibem o novo valor de inteiro e a nova representao de bits, respectivamente. O operador de deslocamento esquerda (<<) desloca os bits de seu operando esquerdo para a esquerda pelo nmero de bits especicado em seu operando direito. Os bits mais direita so substitudos por 0s; os 1s deslocados para fora da esquerda se perdem. As duas primeiras janelas de sada da Figura O.7 demonstram o operador de deslocamento esquerda. Para produzir a sada, o usurio forneceu o valor 23 e deu um clique no boto de deslocamento esquerda, resultando no valor 46. O operador de deslocamento direita (>>) muda os bits de seu operando esquerdo para a direita pelo nmero de bits especicados em seu operando direito. Os 0s substituem os bits vagos no lado esquerdo se o nmero for positivo, e os 1s substituem os bits vagos se o nmero for negativo. Todos os 1s deslocados para fora da extrema direita se perdem. A terceira e a quarta janela de sada descrevem o resultado da mudana 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 atribuio. A Figura O.8 descreve esses operadores de atribuio bit a bit, os quais so usados de modo semelhante aos operadores de designao aritmtica apresentados no Captulo 3.
O-181
Operador de atribuio OU bit a bit exclusivo. Operador de atribuio de deslocamento esquerda. Operador de atribuio de deslocamento direita.
1 2 3 4 5 6 7 8 9 10 11 12
// Fig. O.9: BitArrayTest.cs // Demonstra a classe BitArray. using using using using using using System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data;
O-182
C# Como Programar
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
{ private System.Windows.Forms.Label promptLabel; // o usurio fornece o inteiro private System.Windows.Forms.TextBox inputTextBox; // exibe nmeros primos private System.Windows.Forms.TextBox outputTextBox; // exibe se o inteiro da entrada primo private System.Windows.Forms.Label displayLabel; private BitArray sieve; private System.ComponentModel.Container components = null; // construtor padro public BitArrayTest() { InitializeComponent(); // cria o BitArray e congura todos os bits como verdadeiro sieve = new BitArray( 1024 ); sieve.SetAll( true ); int nalBit = ( int ) Math.Sqrt( sieve.Length ); // executa a operao de peneira for ( int i = 2; i < nalBit; i++ ) if ( sieve.Get( i ) ) for ( int j = 2 * i; j < sieve.Length; j += i ) sieve.Set( j, false ); int counter = 0; // exibe os nmeros primos for ( int i = 2; i < sieve.Length; i++ ) if ( sieve.Get( i ) ) outputTextBox.Text += i + ( ++counter % 7 == 0 ? \r\n : } // cdigo gerado pelo Visual Studio .NET [STAThread] static void Main() { Application.Run( new BitArrayTest() ); } private void inputTextBox_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e ) { // se o usurio pressionou Enter if ( e.KeyCode == Keys.Enter ) { int number = Convert.ToInt32( inputTextBox.Text );
);
O-183
71 72 73 74 75 76 77 78 79 80 81
// se a peneira verdadeira no ndice do inteiro // fornecido pelo usurio, ento o nmero primo if ( sieve.Get( number ) ) displayLabel.Text = number + is a prime number; else displayLabel.Text = number + is not a prime number; } } // m do mtodo inputTextBox_KeyDown } // m da classe BitArrayTest
Usamos um BitArray para implementar o algoritmo. O programa exibe os nmeros primos do intervalo de 1 a 1023 em uma TextBox. O programa tambm fornece uma TextBox na qual os usurios podem digitar qualquer nmero de 1 a 1023 para determinar se aquele nmero primo (caso em que ele exibe uma mensagem indicando que o nmero primo). A instruo da linha 35 cria um BitArray de 1024 bits. O mtodo BitArray SetAll congura todos os bits como true na linha 36; em seguida, as linhas 41 a 44 determinam todos os nmeros primos ocorridos entre 1 e 1023. O inteiro nalBit determina quando o algoritmo est completo. Quando o usurio insere um nmero e pressiona Enter, a linha 73 testa se o nmero da entrada primo. Essa linha usa o mtodo Get da classe BitArray, a qual toma um nmero 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 seqncias de bits. Cada bit pode assumir o valor 0 ou o valor 1. Em todos os sistemas, uma seqncia de 8 bits forma um byte a unidade de armazenamento padro de uma varivel do tipo byte. Os outros tipos de dados exigem nmeros maiores de bytes para o armazenamento. O operador E bit a bit congura cada bit do resultado como 1 se os bits correspondentes em ambos os operandos for 1. O operador OU bit a bit inclusivo congura 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 congura cada bit do resultado como 1 se o bit correspondente em exatamente um operando for 1. O OU exclusivo tambm conhecido como XOR. O operador de deslocamento esquerda (<<) desloca os bits de seu operando esquerdo para a esquerda pelo nmero de bits especicados em seu operando direito.
O-184
C# Como Programar
O operador de deslocamento direita (>>) desloca os bits de seu operando esquerdo para a direita pelo nmero de bits especicados em seu operando direito. Se o operando esquerdo for negativo, os 1s so deslocados a partir da esquerda, enquanto se o operando esquerdo for positivo, os 0s so deslocados a partir da esquerda. O operador de complemento bit a bit (~) congura todos os bits 0 de seu operando como 1 no resultado e congura todos os bits 1 como 0 no resultado; esse processo tambm chamado de tomar o complemento de um do valor. Com freqncia, o operador E bit a bit usado com um operando de mscara um valor de inteiro com bits especcos congurados como 1. As mscaras 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 atribuio. A classe BitArray facilita a criao e manipulao dos conjuntos de bits, os quais so muito usados pelos programadores para representar um conjunto de ags booleanos. Um ag booleano uma varivel que registra determinada deciso booleana. Os BitArrays so 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 mtodo 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 mtodo BitArray And executa um E bit a bit entre dois BitArrays. Ele retorna o BitArray que o resultado da execuo dessa operao. Os mtodos Or e Xor executam o OU bit a bit inclusivo e OU bit a bit exclusivo, respectivamente. O mtodo BitArray SetAll congura todos os bits de BitArray como true.
Terminologia
& (E bit a bit) &= (operador bit a bit de atribuio E) ^ (OU bit a bit exclusivo) | (OU bit a bit inclusivo) |= (operador de atribuio OU bit a bit inclusivo) ~ (operador de complemento bit a bit) << (operador de deslocamento esquerda) <<= (operador de atribuio de deslocamento esquerda) >> (operador de deslocamento direita) >>= (operador de atribuio de deslocamento direita) ALU (Arithmetic Logic Unit unidade lgica aritmtica) bit bit de ordem inferior bit de ordem superior BitArrayText.cs BitSht.cs byte classe BitArray complemento de um (~) conjunto de bits CPU (Central Processing Unit unidade de processamento central) deciso booleana E bit a bit (&) ag booleano indexador BitArray manipulao de bits mscara de bits mtodo And da classe BitArray mtodo Get da classe BitArray mtodo Or da classe BitArray mtodo Set da classe BitArray mtodo SetAll da classe BitArray mtodo Xor da classe BitArray nvel de bits e bytes nmero primo operador de atribuio bit a bit E (&=) operador de atribuio de deslocamento direita (>>=) operador de atribuio de deslocamento esquerda (<<=) operador de atribuio OU bit a bit exclusivo (^=) operador de atribuio 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 atribuio bit a bit operadores bit a bit peneira de Erasttenes propriedade Length da classe BitArray representao binria representao de bits de um inteiro sistema de numerao base 2 sistema de numerao binrio tipo de dados primitivo byte XOR (OU exclusivo)