Tags: , , | Categories: C#, Linguagem de Programação Posted by Rafael on 11/01/2011 19:03 | Comentários (1)

Olá pessoal!

Falaremos hoje sobre operadores C#, em especial sobre os operadores shift, << e >> . A função desses operadores é deslocar bits para a esquerda ( << ) ou para a direita ( >> ), que podem ser utilizados apenas em operações com variáveis do tipo inteiro, pois, não existem números reais na base 2 (binários), apenas números inteiros.

Para entender melhor, vamos falar um pouco sobre números binários e inteiros.

Consideremos a seguinte tabela:

Essa é uma tabela para facilitar a representação de números inteiros em binários. Na linha superior (em azul) temos o expoente da base. Como a base que iremos trabalhar é binária, ou seja, base 2, a linha amarela representa o resultado da potenciação entre a base 2 e seus expoentes. Assim, temos 20 = 1, 21 = 2, 22 = 4, 23 = 8, ..., 210 = 1024, ..., e assim por diante (limitei até o expoente 10 apenas para facilitar a exemplificação).

Muito bem, agora, vamos representar o número inteiro 100 em binário. Na linha amarela, partimos sempre da esquerda para a direita, até encontrar o primeiro número menor ou igual ao número que queremos representar, que nosso caso é o inteiro 100.

Localizamos que o número 64 é o primeiro número menor ou igual a 100, da esquerda para a direita. Assim, “ligamos” o flag, ou seja, inserimos o número 1, da seguinte maneira:

Feito isso, partimos para o segundo bit. Devemos ter em mente o quanto resta para chegarmos a 100 inteiros. A conta é bem simples: se já “ligamos” o 64, a subtração entre 100 e 64 é igual a 36. A partir de agora, localizamos o primeiro número menor ou igual a 36, a partir da primeira célula à direita do flag que representa 64, que é 32.

Como 32 é menor ou igual a 36, ativamos também essa célula, ficando assim:

Legal, agora nos restam 4 inteiros (100 – 64 – 32 = 4). Dando seqüência, como 16 não é menor ou igual a 4, inserimos um 0, ou seja, “desligamos” o flag da célula 16, assim:

Da mesma maneira, fazemos com a célula 8, pois 8 não é menor ou igual a 4, ficando assim:

Como 4 é menor ou igual a 4, “ligamos” o flag, da seguinte maneira:

Como chegamos a 100 inteiros, completamos as células restantes à direita com 0, assim:

Temos agora o número inteiro 100 representado em binário como 1100100.

Muito bom! Agora que já sabemos como representar inteiros em binários de uma forma fácil, vamos entender como os operadores shift trabalham.

Basicamente, como dito anteriormente, o operador shift << desloca um bit à esquerda, inserindo um 0 (zero) na célula vazia, e o operador >> desloca um bit à direita, desconsiderando o bit que “sai” do range. Vamos exemplificar com um Console Application em C#, bem simples, junto com a nossa tabela de conversão.

Consideremos o seguinte Console Application:

namespace Blog.Operadores.Shift

{

    class Program

    {

        static void Main(string[] args)

        {

            try

            {

                Console.WriteLine("Insira um número inteiro:");

 

                int inteiro = 0;

                Int32.TryParse(Console.ReadLine(), out inteiro);

 

                Console.WriteLine("Número inteiro escolhido: " + inteiro.ToString());

 

                Console.WriteLine("");

 

                Console.WriteLine("Quantos bits você deseja deslocar?");

 

                int qtdeBits = 0;

                Int32.TryParse(Console.ReadLine(), out qtdeBits);

 

                Console.WriteLine("Bits a deslocar: " + qtdeBits.ToString());

 

                Console.WriteLine("");

 

                Console.WriteLine("À esquerda ou à direita? Digite << para à esquerda e >> para à direita:");

 

                string comando = Console.ReadLine();

 

                if (comando.Trim() != "<<" && comando.Trim() != ">>")

                {

                    throw new Exception("Comando inválido! Você deve escolher entre << e >>");

                }

 

                switch (comando.Trim())

                {

                    case "<<":

                        Console.WriteLine("Bit deslocado à esquerda");

                        inteiro = inteiro << qtdeBits; // forma simplificada: inteiro <<= qtdeBits;

                        break;

                    case ">>":

                        Console.WriteLine("Bit deslocado à direita");

                        inteiro = inteiro >> qtdeBits; // forma simplificada: inteiro >>= qtdeBits;

                        break;

                    default:

                        break;

                }

 

                Console.WriteLine("");

                Console.WriteLine("Resultado: " + inteiro.ToString());

            }

            catch (Exception ex)

            {

                Console.WriteLine("");

                Console.ForegroundColor = ConsoleColor.Red;

                Console.WriteLine("ERRO: " + ex.Message);

            }

            finally

            {

                Console.ResetColor();

                Console.ReadKey();

            }

        }

    }

}

Se preferir, faça o download do projeto aqui: Blog.Operadores.Shift.zip (19,21 kb)

Note os dois comentários // forma simplificada no código. Podemos escrever tanto assim x = x << y quanto x <<= y ou então x = x >> y quanto x >>= y. A segunda opção é a forma simplificada do comando. Muda apenas a sintaxe, o resultado é o mesmo.

Ao executarmos o aplicativo, temos a seguinte tela:

Para seguir o nosso exemplo, vamos inserir o número 100.

Vamos deslocar apenas 1 bit à esquerda.

Na tabela, podemos ver como pode ser feito manualmente:

Todos os bits são deslocados 1 (uma) casa para a esquerda, e a célula vaga é preenchida com 0 (zero).

Assim, temos o número inteiro 200 como resultado. Agora vamos executar novamente o aplicativo, porém, agora deslocando 1 bit à direita.

Na tabela:

Obtemos como resultado 50 inteiros.

Logo, podemos notar que, se deslocarmos 1 bit à esquerda, multiplicamos o número por 2, e se deslocar à direita, dividimos também por 2. Agora, porque por 2? A resposta é bem simples, como estamos trabalhando com binários, ou seja, base 2, o deslocamento de bits multiplica ou divide o valor pela base, que é 2.

Agora, se deslocarmos 3 bits à direita de 100, temos como resultado 12. Você pode me perguntar: porque não 12,5? A resposta também é simples: porque não existem números reais por representação de bits, ou seja, o resultado 12,5 é truncado, ficando apenas 12.

Vamos ver na tabela:

E na aplicação:

É isso aí.

Até a próxima!

Tags: , | Categories: Padrões de Projeto Posted by Rafael on 03/01/2011 21:30 | Comentários (2)

Antes de qualquer coisa, quero nesse primerio post de 2011, desejar a todos vocês que acompanham o meu blog um Feliz 2011 com muita paz, saúde, sucesso e felicidade! Que Deus abençoe a todos vocês e os guie e guarde sempre!

Hoje falaremos sobre um dos padrões mais utilizados, o padrão Factory Method. Também conhecido como Virtual Constructor, tem por objetivo definir uma interface para a criação de um objeto, delegando a decisão sobre qual classe instanciar para as subclasses.

Já fizemos uso do padrão Factory Method tanto quando implementamos o padrão Abstract Factory, quanto quando implementamos o padrão Adapter. Além desses, o padrão Factory Method é utilizado na implementação de vários outros padrões. Isso demonstra o quão utilizado é o padrão Factory Method.

Utilizamos o padrão Factory Method quando queremos separar a lógica que define qual classe instanciar do aplicativo cliente, ou seja, a classe ou aplicativo cliente invoca um método de uma subclasse que retorna a instancia de uma outra classe de acordo com uma lógica específica, encapsulando assim o conhecimento sobre qual classe deve ser instanciada. A classe cliente tem apenas o conhecimento de quando criar a classe desejada, mas não possui o conhecimento de qual classe criar ou como a criar.

O padrão Factory Method segue o seguinte padrão:

Vou utilizar o exemplo o post anterior, para facilitar. Você pode baixar o código fonte do exemplo aqui.

Vamos analisar os objetos do exemplo:

 

Program.cs

class Program

{

    static void Main(string[] args)

    {

        ITerminal34 terminal = ComponenteHidraulicoFactories.ObterTerminal();

        terminal.Acoplar();



        Console.ReadKey();

    }

}

 

ComponenteHidraulicoFactories.cs

public class ComponenteHidraulicoFactories

{

    public static ITerminal34 ObterTerminal()

    {

        return new Adaptador12para34();

    }

}

 

ITerminal34.cs

public interface ITerminal34

{

    void Acoplar();

}

 

Adaptador12para34.cs

public class Adaptador12para34 : ITerminal34

{

    public void Acoplar()

    {

        Torneira12.Acoplar12();

    }

}

 

A classe Program (cliente) determina o momento (quando) em que uma instância de uma classe do tipo ITerminal34 deve ser criada, mas não como ou qual deve ser criada. Isso cabe ao método ObterTerminal() da classe ComponenteHidraulicoFactories, que retorna uma instância de Adaptador12para34, que por sua vez, implementa a interface ITerminal34.

O método ObterTerminal() da classe ComponenteHidraulicoFactories implementa o padrão Factory Method pois encapsula a logica de qual classe instanciar e como ela é instanciada, retornando apenas a instancia da classe escolhida, já criada.

Esse é o Factory Method. Um padrão simples e muito utilizado.

Até a próxima!