Primeiramente, por que falar de números pares ou ímpares? A resposta é "porque parece fácil". Quando estamos falando de números em base 10 pode-se olhar para o último dígito e verificar se é par ou não. Com números em base 2 é só verificar se o último dígito é zero (em números pares) ou um (números ímpares).
Determinação de Paridade (até agora)
Sabendo que o computador usa representação binária, podemos usar um operador que faz operações bit a bit de uma linguagem de programação (abaixo faço em Python) para determinar a paridade de um número verificando apenas se o bit menos significativo é zero.
even_number & 1 == 0
> True
odd_number & 1 == 0
> False
Fim do problema?
Sim e não. Se estivermos falando de uma linguagem de programação de alto nível, é provável que o dito acima seja o suficiente para determinar paridade. Também é provável que o compilador ou JIT troque testes de paridade na forma number % 2 == 0
por códigos mais parecidos com os da seção acima.
O problema começa quando estamos mais perto do hardware, lidando com protocolos de transmissão de informação ou simplesmente brincando de fabricar hardware ou testar arquiteturas usando protoboards.
A operação acima é facilmente implementável em hardware com apenas uma porta lógica AND
.
Representação de números no hardware
Em geral se agrupa os dígitos binários de 8 em 8 para trabalhar com bytes. Saber desse agrupamento é necessário para falar sobre Endianness: big-endian, little-endian e middle-endian.
Endianness
Vou começar dizendo que não vou falar de middle-endian, apesar de interessante, essa explicação não me ajuda muito porque não encontrei nenhum exemplo de uso que combine com a discussão de paridade. Mas a representação middle-endian está bem explicada no link providenciado.
Pensando no "fim" do número como a parte mais à esquerda, é como falamos em endianness.
Big-endian
Big-endian é a representação usual, em que o byte mais significativo é o que está no "fim" como definido acima.
Little-endian
Little-endian é o oposto da representação usual, em que o byte menos significativo é o que está no "fim". Ou seja, a parte menor do número aparece no "fim" (lado esquerdo) em vez de aparecer do lado direito. Um outro problema é que isso é uma inversão de bytes, mas não de bits dentro dos bytes. Vale olhar a imagem abaixo em conjunto com a imagem na seção de Endianness.
Gray Code
Para algumas aplicações que precisam evitar interferências e erros, existe uma outra forma de codificar números em que números seguidos mudam em apenas um bit.
Decimal | Binary | Gray |
---|---|---|
0 | 0000 | 0000 |
1 | 0001 | 0001 |
2 | 0010 | 0011 |
3 | 0011 | 0010 |
4 | 0100 | 0110 |
5 | 0101 | 0111 |
6 | 0110 | 0101 |
7 | 0111 | 0100 |
8 | 1000 | 1100 |
9 | 1001 | 1101 |
10 | 1010 | 1111 |
11 | 1011 | 1110 |
12 | 1100 | 1010 |
13 | 1101 | 1011 |
14 | 1110 | 1001 |
15 | 1111 | 1000 |
A tabela acima foi copiada da Wikipedia, do artigo sobre Gray Code. Os circuitos que checam o bit menos significativo não são o suficiente para determinar paridade, talvez não seja um circuito difícil de fazer, mas não tão óbvio. Seguindo uma extensa tradição matemática, deixo esse circuito como exercício para o leitor.
Conclusão
Hardware, essa coisa concreta e absolutamente necessária para a computação contemporânea, pode tornar mais difícil fazer operações que podem parecer óbvias. Em geral, temos soluções para isso no meio do ferramental de linguagens de programação e podemos só ler os números da forma que leríamos no papel.
Mas quando se considera toda a teoria e protocolos em todo o caminho desde digitar um número no teclado até acender um bit na memória, as coisas podem se tornar muito mais complexas apesar de o problema em si ser bastante simples. Esse texto não chegou a mencionar representações em Complemento a 2 nem citar arquiteturas específicas que usam uma ou outra representação, também não falei de consequências disso em conjuntos de instruções. Então o universo que cerca esse problema simples e que eu não explorei continua enorme e é super interessante.
Top comments (0)