Operadores Bitwise – Matemática Lógica Aula 2 de 2

Ver o tópico anterior Ver o tópico seguinte Ir em baixo

Operadores Bitwise – Matemática Lógica Aula 2 de 2

Mensagem por GameMakerTutoriais em Qui 17 Nov 2011, 03:51

Vou postar novamente os dois tutoriais sobre operadores bitwise porque tinham se perdido com o backup do fórum. blz




Operadores Bitwise – Matemática Lógica 2ª Parte

Por: BrendanLS (bl8086)

Na aula passada vimos como a matemática lógica foi importante para todo o avanço que nós, seres humanos, tivemos na tecnologia e na ciência. É a partir de comparações simples entre valores de 0 e 1 que são realizados todos os cálculos feitos pelo processador. Vimos também que as três operações básicas para bits são AND, OR e NOT. Também temos a operação XOR, que vou explicar com mais calma em outra oportunidade, por enquanto, vamos focar nosso raciocínio nas três que já sabemos.

Toda vez que instruímos o processador para que faça uma operação, os dados são carregados para dentro dele em um lugar que chamamos de registradores. Registradores são pequenas áreas de memória onde os dados ficam disponíveis para a Unidade Lógica Aritmética, que fará as operações de acordo com as instruções dos programas.

A Unidade Lógica Aritmética, ou ALU (Arithmetic Logic Unit) é uma área do processador dedicada para realizar cálculos lógicos entre o que há nos registradores. Ela pode pegar dois valores e somar, subtrair, pegar um valor e preencher com vários bits iguais, deslocar bits, verificar se um bit é 0 ou 1, ou comparar se um número é maior ou menor que outro. Quando essas operações são realizadas, o resultado pode ser jogado em um ou mais registradores de saída. Essa é a nossa fonte de operação!

Nós já sabemos que um byte pode comportar até 256 valores, portanto, de 0 à 255 e quando temos um número maior que este, teremos que usar um byte extra.

Com dois bytes, temos 256 x 256 = 65536 possibilidades, portanto, de 0 à 65535. É por isso que existem diferentes tipos de variáveis em programação, pois variável nada mais é do que uma área de memória que é alocada para se armazenar um valor qualquer. Mas para que não haja confusão ao operar com essas áreas, devemos especificar o ponto em que ela começa e o seu tamanho. Mas por hora, vamos nos manter apenas no conceito do cálculo, pois isso nós vamos entender quando eu explicar sobre como a memória é dividida.

Vamos então, usar dois números que usam 1 byte e trabalhar com eles. Em base binária, o valor 135 é representado por 10000111. O nosso outro número será o 216, que em binário é dado por 11011000. Quando usarmos os operadores lógicos, eles vão operar sobre cada bit individualmente.


Carlos é alto.
Carlos é gentil



Operador AND ( & ) / Conjunção ( E )

Carlos é alto E Carlos é gentil

Essa frase só pode ser verdadeira se ambos os comparativos forem verdade, portanto, o operador AND retornará 1 sempre que os dois bis comparados forem 1. Em qualquer outra situação ele retornará 0. Vamos aplicar isso na prática usando nossos números. Comparando cada bit, veremos que só o primeiro ainda será 1, pois em ambos os números, este bit está “ligado”. O resultado da operação será o número 128:


Exemplo em Pascal:
Código:
n := 135 and 216;

Exemplo no Game Maker:
Código:
n := 135 & 216;




Operador OR ( | ) / Disjunção ( OU )

Carlos é alto OU Carlos é gentil

Essa frase só poderá ser verdadeira se pelo menos uma das condições for verdadeira. Da mesma forma, o operador OR retornará 1 bit em casos onde pelo menos 1 dos bits comparados for 1. No nosso exemplo, apenas o terceiro bit da esquerda para a direita está desligado em ambos. Em todos os demais, o retorno será 1. No final teremos o número 223, que em binário é 11011111.


Exemplo em Pascal:
Código:
n := 135 or 216;

Exemplo no Game Maker:
Código:
n := 135 | 216;

Operador NOT ( ~ ) / Negação ( NÂO )

Carlos NÃO é alto.
Carlos NÃO é gentil

O operador NOT nega o valor seguinte. Todos os bits que forem 1 se tornarão 0 e vice-versa. Há uma coisa importante a ser frisada aqui. Sempre que lidamos com qualquer operador lógico, todos os bits usados para alocar um tipo de valor na memória são usados nas operações.

Se temos uma variável do tipo Byte, sabemos que ela gasta 8 bits para ser armazenada na memória. Digamos que essa variável Byte esteja armazenando o número 4. Sabemos que esse valor em binário usa apenas três bits (100 em binário), no entanto, quando usamos o operador de negação, todos os bits reservados para alocar a variável serão usados (que nesse caso serão 8 ). Essa regra vale também para variáveis do tipo inteiro ou booleana. Então, como exemplo, vamos usar o número 4 (tipo byte):


“Mas por quê, quando eu uso a negação lógica, é retornado um número negativo?”. Isso acontecerá se você estiver trabalhando com um número inteiro, e não um byte. No Game Maker, por exemplo, não há diferenciação de tipos de variáveis numéricas! A quantidade de bytes que ele aloca (que eu acredito ser 8 ) é usada também para armazenar números negativos.

Se você fizer o mesmo procedimento com uma variável de tipo inteiro em Pascal, terá um número negativo também. É bom ressalvar que nos exemplos que dei nesse tutorial, estamos usando apenas valores Byte. Portanto, tenha uma atenção especial com esse operador no Game Maker. Em C ou Pascal não há o que se preocupar, apenas atente aos tipos de variáveis e estará tudo certo.

Exemplo em Pascal:
Código:
negado := not valor;

Exemplo no Game Maker:
Código:
negado := ~valor;

Operadores Bit Shift


Esses não são operadores lógicos, mas auxiliam muito nos processos de operação. O que esses operadores fazem é deslocar os bits para a esquerda ( << ) ou para a direita ( >> ), completando os “espaços faltantes” com 0. Sempre teremos que indicar quantos bits deverão ser deslocados. Nos exemplos abaixo, vamos deslocar 2 bits para a esquerda no valor 135. Depois, deslocaremos 3 para a direita usando o mesmo valor:


Eles também são muito úteis quando se trabalha com valores muito altos que usam mais de 1 byte.


Um exemplo prático simples

Essa foi a segunda parte da nossa aula sobre operadores lógicos. Espero que com esses exemplos, todo esse conceito tenha ficado mais claro agora. Daqui em diante usaremos esses operadores sempre que trabalharmos com bits. Então, vamos à mais um pequeno exemplo prático de como usar esses operadores em tarefas corriqueiras em programação. Isso também será bom para reforçar nosso aprendizado.

Na nossa aula sobre RGB em games vimos que quando usamos o padrão True Color cada pixel de cor em uma imagem é representado por 3 bytes apenas, um para cada cor primária. Apesar de que o padrão é dado por Red, Green e Blue, não é necessariamente essa a ordem em que os valores são alocados na memória. Ao lidar com números reais, a ordem correta desses bytes é BGR. O primeiro byte é o valor de azul, o segundo de verde e o terceiro é o vermelho. Essa é a nossa fonte

Sabendo disso, podemos “brincar” com esses três bytes, arrastando os valores para a direita ou esquerda, e combinando com outros através de operações lógicas. Também podemos “pegar” cada componente separadamente. Como exemplo, vou usar o Game Maker, pois é mais fácil.

Para pegar o valor do vermelho, vamos usar o operador AND. Como ele retorna 1 bit sempre que ambos os bits comparados forem 1, basta que a gente compare o valor da cor com um número que preencha o byte vermelho com vários 1s, ou seja, 255 (que é 1 byte “completo”). Veja:

Código:
vermelho_da_cor  = cor & 255

Para pegar o valor do verde, basta fazer o mesmo procedimento que fizemos com o vermelho, porém, vamos deslocar 1 byte (8 bits) para a direita antes de fazê-lo. Veja:

Código:
verde_da_cor  = (cor >> 8 ) & 255

Para pegar o azul, é o mais fácil de todos. Como ele é o primeiro byte da esquerda para a direita, vamos deslocá-lo 2 (16 bits) bytes para a direita:

Código:
azul_da_cor = cor >> 16


Última edição por Ninja8086 em Qua 29 Fev 2012, 16:29, editado 1 vez(es)

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Operadores Bitwise – Matemática Lógica Aula 2 de 2

Mensagem por saim em Qua 29 Fev 2012, 15:41

Ok, consegui entender mais essa aula. Tenho algumas observações a fazer:
- 216 é 11011000 e não 110011000. Isso me confundiu um pouco.
- o "not" (~) realmente inverte o sinal no game maker, mas não é só isso, ele também aumenta o módulo e elimina as casas decimais. Não sei como o game maker trabalha com casas decimais ou números negativos. Talvez uma aulinha extra explique esse "fenômeno".
- o "not" ("!" ou "not" mesmo), no game maker, inverte true pra false e vice-versa. Isso vale pra valores diferentes de 0 e 1, já que o game maker é uma vadia que aceita qualquer coisa - de menos infinito até 0.5, é false, de 0.5 (inclusive) pra cima é true.
- faltou explicar o xor e mostrar alguma utilidade pra ele. O mais difícil de mostrar alguma utilidade, que era o bit shift, você mostrou. O xor ficou de fora.

Beleza, ninja, agora vou tentar entender aquele código das mp3 de novo!
Já que NESSE tutorial ninguém comentou ainda, PARABÉNS.

saim

Ranking : Nota B
Número de Mensagens : 2964
Idade : 38
Data de inscrição : 14/01/2011
Notas recebidas : C-D-A-B
Reputação : 121
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 1
   : 0
   : 3

Voltar ao Topo Ir em baixo

Re: Operadores Bitwise – Matemática Lógica Aula 2 de 2

Mensagem por GameMakerTutoriais em Qua 29 Fev 2012, 21:11

- 216 é 11011000 e não 110011000. Isso me confundiu um pouco.

Vixi, passou batido isso. Valeu pelo toque, já arrumei lá em cima. Very Happy

- o "not" (~) realmente inverte o sinal no game maker, mas não é só isso, ele também aumenta o módulo e elimina as casas decimais. Não sei como o game maker trabalha com casas decimais ou números negativos. Talvez uma aulinha extra explique esse "fenômeno".

Em binário tem dois jeitos de representar números negativos.

Quando a gente declara uma variável, a gente tá na verdade, alocando uma quantidade de bytes na memória, certo? Uma variável ShortInt, por exemplo, usa 1 byte, uma Integer 2 bytes, uma LongInt usa 4 bytes e assim por diante...

Pra todos esses tipos de variáveis exatas, ou seja, sem ponto flutuante, o valor é dito como negativo ou positivo através de um bit significativo. Essa é a primeira das duas formas. Esse bit é sempre o último da esquerda, ou seja, vai depender da quantidade de bits que foi alocado pra variável. Um exemplo de um valor ShortInt negativo seria:

Código:
00000001 (binário) = +1 (decimal)
10000001 (binário) = -1 (decimal)

Um outro jeito é esse que eu disse no tutorial através do operador de negação binária (~). Esse jeito inverte todos os bits, e consequentemente o bit significativo também. Ou seja, todo número negativo começa com o último bit da esquerda "ligado". Ok, mas aí tem uma observação a ser feita também:

Código:
00000001 (binário) = +1 (decimal)
11111110 (binário) = 254 (wtf?)

O valor ShortInt não tem 254, ele só pega o range de -128 a 127! Quando invertemos esse último bit, o valor sempre vai exceder 127, portanto, o que a gente vai fazer é subtrair 255 do valor pra achar a contraparte dele, ou seja, o valor negativo:

Código:
254 - 255 = -1

Daí vem a questão: mas e o "11111111" (255)?? Se você subtrair 255 de 255 é zero, mas nós já temos um zero que é o valor binário "00000000". Pois é. Em representação de números negativos, temos dois zeros binários. Um "00000000" e "11111111". Teoricamente é um zero positivo e um zero negativo. É estranho, mas é assim mesmo.

Ok, mas o que isso tem a haver com o Game Maker? Seguinte... O GM usa uma um valor Double (8 bytes) pra armazenar números na memória, certo? O problema tá no fato de quê Double é um valor de ponto flutuante. Variáveis de ponto flutuante usam os dois métodos que eu falei aí em cima. Esses 64 bits que ela usa são distribuídos entre bit significativo, mantissa e expoente, e esses valores variam. Essa variação é que deixa complicado aplicar a negação binária no Game Maker.

E falando francamente, não conheço muito disso quando se trata de "floats". Essa distribuição é complicada mesmo, por isso que eu disse pra sempre tomar cuidado com esse operador no GM....

- faltou explicar o xor e mostrar alguma utilidade pra ele. O mais difícil de mostrar alguma utilidade, que era o bit shift, você mostrou. O xor ficou de fora.

Tem razão, na verdade eu tinha deixado ele pra colocar uns exemplos a mais, porque eu queria mostrar um Xor usado como condição durante o código e um Xor como operador bitwise. A premissa é a mesma, mas o motivo disso era mostrar como eliminar vários ifs no código... Vou colocar ele aí pra vocês.

Falou! blz



Última edição por Ninja8086 em Qua 29 Fev 2012, 21:58, editado 1 vez(es)

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Operadores Bitwise – Matemática Lógica Aula 2 de 2

Mensagem por Lauro em Qua 29 Fev 2012, 21:21

Puxa cara, muito bom este tutorial, muito bem explicado e exemplificado. Mesmo eu sendo um amador, consegui entender mais deste medonho mundo.
Eu entendi que essa é a parte "aplicável" no mundo tecnológico, e a anterior é mais uma introdução e a história dos binários.

Lauro

Ranking : Nota D
Número de Mensagens : 854
Idade : 19
Data de inscrição : 09/11/2010
Notas recebidas : C+D
Reputação : 11
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.google.com

Voltar ao Topo Ir em baixo

Re: Operadores Bitwise – Matemática Lógica Aula 2 de 2

Mensagem por GameMakerTutoriais em Qua 29 Fev 2012, 21:39

Lauro escreveu:Puxa cara, muito bom este tutorial, muito bem explicado e exemplificado. Mesmo eu sendo um amador, consegui entender mais deste medonho mundo.
Eu entendi que essa é a parte "aplicável" no mundo tecnológico, e a anterior é mais uma introdução e a história dos binários.

Valeu! O tutorial anterior até que não tem muita importância, na verdade são só umas curiosidades mesmo... Mas esse tutorial aqui que eu acho que é mais importante porque depois que a gente pega a lógica, o resto é moleza. Very Happy

@saim

Esqueci de comentar uma coisa, o not do exemplo dado em Pascal não funciona do mesmo jeito que o "not" no Game Maker. O not no Game Maker funciona como o ( ! ), mas não é o mesmo que o ( ~ ). Isso do GM aceitar o estilo Pascal é só uma comodidade mesmo...

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Operadores Bitwise – Matemática Lógica Aula 2 de 2

Mensagem por Conteúdo patrocinado Hoje à(s) 17:53


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo

- Tópicos similares

 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum