Estudos de Bases Numéricas
Tags: webdev, math, braziliandevs, softwareengineering
Published: 2023-08-23 11:03:38

## **Como os números são representados**

Em um primeiro momento precisamos entender como os números são representados. Os números são representados por meio do sistema posicional ou notação posicional.

Cada número ou dígito tem seu valor em função da posição que ocupa na sequência numérica e pela base (sistema) que faz parte. 

Como escreve os professores Profs. [M.Sc](http://m.sc/). Lucio M. Duarte e Ph.D. Avelino Zorzo:

> S*istemas numéricos são posicionais, isto é, cada quantidade é representada em uma única forma, mediante uma certa combinação de símbolos, que têm um significado distinto, segundo sua posição.*
> 

> *No sistema decimal, como já comentado, cada posição tem um valor intrínseco que
equivale a dez vezes o valor da posição que está imediatamente a sua direita.*
> 

Fonte: https://www.inf.pucrs.br/~zorzo/ii/downloads/representacaodedados.pdf

Para sabemos o valor de um número, não basta saber o seu valor individual, mas também qual base ele faz parte e qual a sua posição quando está representando em uma sequência de símbolos. 

Vamos partir a explicação do nosso sistema decimal, ou base 10, o qual já estamos acostumados a utilizar. 

A exemplo, o número `422`. 

O qual pode escrito da seguinte forma:  

***422 = 4x100 + 2x10 + 2x1***

Ou da seguinte forma. 

***422 = 4x10^2 + 2x10^1 + 2x10^0***

Explicando: 

Para sabermos o valor do `4`, que representa `400`, temos que saber a sua posição, contando da direita para a esquerda começando com zero. Que nesse caso é `2`. Deve observar que consideramos o início da contagem das posições da direita para a esquerda. 

Depois multiplicamos `4` pela base, neste caso `10`, elevada a sua posição: `2`.

***4*10^2 = 4*100 = 400***

Para o valor de `2` que representa `20`. 

***2*10^1 = 2*10 = 20***

E para o valor de `2` que `2`;

***2*10^0 = 2*1 = 2***.

Somamos os resultados: `400 + 20 + 2 = 422`.  

Concluindo. O valor do símbolo depende da posição que ocupa em relação a todo o conjunto que está representando, bem como da base que está sendo utilizada na representação. 

Nesse sentido, podemos obter a partir da seguinte equação de contagem:

$$
D\;=\;\sum_{i\;=\;-n\;}^{p-1}\;d_i\;\times\;r^i\;=d_{p-i}\times r^{p-1}+...+d_1\times r^1+d_0\times r^0+d_{-1}\times r^{-1}+...+d_{-n}\times r^{-n}
$$

Onde: 

– D : número;
– r : base ou *radix*;
– d : dígito (`0 ≤ d < r`);
– p : quantidade de dígitos na parte inteira;
– n : quantidade de dígitos na parte fracionária;

Por fim uma observação importante:

> Observa-se que os sistemas não posicionais dificultavam a representação de números
“grandes”, ou seja, era necessário muitos símbolos para isso. Por outro lado, em um sistema
posicional é possível representar números cada vez maiores com os mesmos símbolos. Outra
grande vantagem do sistema de numeração com valor posicional é que as operações (adição,
subtração, multiplicação e divisão) são de execução bem mais simples.
Em um sistema de numeração posicional o número nove, por exemplo, não tem o
mesmo valor quando está colocado na fileira nas unidades, dezenas, centenas e, assim por
diante. Por exemplo, 959 – No sistema de numeração que usamos hoje, 9 na unidade, tem
como valor posicional nove unidades, na centena o 9 tem valor novecentos. Nesse sistema,
o valor de um algarismo depende da posição que ele ocupa no número.
> 

fonte: https://repositorio.ufgd.edu.br/jspui/bitstream/prefix/1375/1/KatiuceFernandesRocha.pdf 

Mais informações:

[https://pt.wikipedia.org/wiki/Notação_posicional](https://pt.wikipedia.org/wiki/Nota%C3%A7%C3%A3o_posicional) 

[https://edisciplinas.usp.br/pluginfile.php/4190820/mod_resource/content/5/PCS3115 2018S1 Sistemas de Numeracao v2.pdf](https://edisciplinas.usp.br/pluginfile.php/4190820/mod_resource/content/5/PCS3115%202018S1%20Sistemas%20de%20Numeracao%20v2.pdf) 

## Bases numéricas

Uma base numérica representa uma quantidade de símbolos possíveis que podemos utilizar para representar um número. 

A elas temos a seguinte definição formal.

**Definição** (Sistema de numeração de base `b`)**.** *Dado um número natural* `b`>1 *e o conjunto de símbolos* {±,0,1,2,…,`b`−1}*,* *a sequência de símbolos*

$$
(d_nd_{n-1}..d_1d_0,d_{-1}d_{-2}...)_b
$$

*representa o número positivo*

$$
d_n⋅b^n+d_{n-1}⋅b^{n-1}+\cdots+d_0⋅b^0+d_{-1}⋅b^{-1}+d_{-2}⋅b^{-2}+\cdots
$$

*Para representar números negativos usamos o símbolo* − *a esquerda* *do numeral*.

Mais informações: https://www.ufrgs.br/reamat/CalculoNumerico/livro-py/rdneadm-sistema_de_numeracao_e_mudanca_de_base.html

> Assim, escolhemos um número `b` como base e `b` símbolos, um para cada número de `0 a b − 1`, chamados de algarismos (dígitos). Multiplicando um destes números (algarismos) pelas potências de `b (1, b^2, b^3, etc.)` e somando-os, conseguimos expressar um número em uma determinada base. Por exemplo, `1352 = 1 · 10^3 + 3 · 10^2 + 5 · 10^1 + 2 · 10^0`. Esse número, por exemplo, está representado na base decimal, ou seja, `b = 10` .
> 
> 
> Assim, os algarismos em qualquer número dado representa um múltiplo de alguma potência da base, potência essa que depende da posição ocupada pelo algarismo. Como exemplo de sistema posicional temos nosso sistema de numeração posicional decimal indo-arábico. 
> 
> Nesse sistema, por exemplo, `5` em `506` representa `5 · 10^2` ou `500`. Agora, `5` em `58` representa `5 x 10^1` ou `50`. Observe que o zero é importante para indicar a ausência de alguma potência da base.
> 

Fonte: https://repositorio.ufgd.edu.br/jspui/bitstream/prefix/1375/1/KatiuceFernandesRocha.pdf

São várias as bases numéricas, mas aqui apenas trataremos de estudar algumas mais utilizadas no ambiente de programação. Quais são:

1. Binária;
2. Octal;
3. Decimal;
4. Hexadecimal;

Em seguida falarei um pouco sobre cada um delas. 

### Base Binária

No sistema binário ou base binária temos apenas dois símbolos para compor os números. São: `0` e `1`.  Por isso é chamado de binário em razão da quantidade de símbolos que fazem parte: dois. 

São incluídos como símbolos pertencentes a determinada base iniciando-se em `0` até `b - 1`. Conforme explicado, acima, na definição formal de bases numéricas. 

Que neste caso são:

$$
{0, 1}
$$

Onde cada símbolo ou digito tem o seu valor em função do produto da multiplicação dele por 2 elevado a n-enésima posição. Ou seja, construímos a representação de um número qualquer somando as potências de dois presentes na representação. 

Como temos apenas `0` e `1` como dígitos disponíveis, quando temos um valor a ser considerado e quando temos zero, dispensa-se a explicação.  

| Posição | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Valor | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |

Exemplos de representação de números decimais na base binária:

**2 = 00010**

**4 = 00100**

**10 = 1010**

**25 = 11001**

É a base que os sistemas computacionais entendem e operam. Diferente de nós que utilizamos o sistema decimal. Dado que utilizam os seguintes algarismos: 1 bit (para indicar presença de tensão) e 0 bit (para indicar ausência de tensão).

Toda operação computacional primeiro converte o número para base `2`, realiza as operações e depois converte para a base original, qual seja: decimal, hexadecimal ou outra que o usuário esteja utilizando. 

### Base Octal

Base octal ou base 8 (oito). Nesta base temos 8 (oito) algarismos para representar um número qualquer. São:

$$
{0, 1, 2, 3, 4, 5, 6, 7}
$$

Exemplos de números na base dez e sua representação na base octal:

**4 = 4**

**10 = 12**

**42 = 52**

**127 = 177**

Mais na frente será demonstrado como é feita a conversão acima exemplificada. 

### Base Decimal

A base decimal ou base 10 (dez) é que utilizamos no nosso dia a dia. Ela dispõe de 10 (algarismos) para representar os números. Quais são:

$$
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
$$

### Base Hexadecimal

A base hexadecimal ou base 16 (dezesseis) são utilizados dezesseis símbolos, que vão de `0` até `9` mais as letras `A` até `F`. No qual as letras são equivalentes no sistema decimal aos valores de `10` até `15`.

$$
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F}
$$

Exemplos de números na base dez na base hexadecimal:

**4 = 4**

**10 = A**

**42 = 2A**

**127 = 2F**

**Curiosidade:** Na linguagem Javascript, pode-se obter o valor decimal de número hexadecimal utilizando o prefixo `0x` antes do número na base 16. 

```jsx
console.log(0x7F);
// 127
```

## **Conversão de decimal para para as demais bases**

> Dado um número na base decimal podemos escrevê-lo em qualquer outra base usando sucessivamente a divisão por resto ou Euclidiana. O número que no passo n-ésimo for quociente passa a ser dividendo no passo de ordem n + 1. O processo conclui quando o quociente for zero.
> 

*Referências*: LINARES, Juan López; BRUNO-ALFONSO, Alexys; BARBOSA, Grazielle Feliciani. Bases numéricas na olimpíada internacional de matemática. **Revista Professor de Matemática Online**, v. 7, n. 02, 2019.

Continuando a explicação. Após chegarmos a momento que o consciente for zero, alinhamos os restos da divisão na ordem inversa que foram encontrados. 

Deve-se atentar que deve utilizar o maior quociente inteiro da divisão.  

Converter o número `42` na base `10` para a base `2`:

Para o cálculo do resto utilizaremos o operador módulo, representado por `%`. 

***42 / 2 = 21       42 % 2 = 0***

***21 / 2 = 10       21 % 2 = 1***

***10 / 2 = 5         10 % 2 = 0***

***5  /  2 = 2          5 % 2 = 1***

***2  /  2 = 1          2 % 2 = 0***

***1  /  2 = 0          1 % 2 =  1***

Feitas as divisões sucessivas, basta alinhar os restos na ordem inversa: `101010`. Assim temos a representada do número `42`  na base `10` na base `2`. 

Este mesmo procedimento é para a conversão para qualquer outra base. Basta substituir o dois pela base final desejada. 

### Conversão da parte fracionária

Agora, para conversão de um número fracionário ou de um número com uma parte fracionária separamos a parte inteira da fracionária. Enquanto para a parte inteira realizamos o procedimento acima explicado; utilizando o método das divisões sucessivas. Para o número fracionário ou parte fracionária realizamos multiplicações sucessivas, da parte fracionária, até que o resultado seja apenas inteiros. Ou que repitam, que é quando estaremos diante de uma dizima periódica.

Por exemplo, converter o número `42,75` na base `10` para a base `2`:

A parte inteira do número já foi feito acima, então descartar-se repetir os mesmo cálculos. Aqui é interessante apenas a parte fracionária. 

***0,75 * 2 = 1,5***

***0,50 * 2 = 1***

Nesse caso, diferentemente do que fazemos com a parte inteira, vamos posicionando a parte inteira resultante da multiplicação na ordem que foram calculados, ou encontrados.

No nosso exemplo, tivemos como resultado `11`. 

Desse modo, o `42,75` na base `10` para a base `2` é: `101010,11`. 

## **Conversão das demais bases para decimal**

Para convertemos um número em determinada base para decimal, basta aplicar a definição do que vimos quando escrevi sobre **************************bases numéricas************************** linhas acima. 

Relembrando. Para conseguir o valor do número, na base dez, a partir de determinada base fazemos o seguinte.

Multiplicamos os dígitos pela base elevada a sua posição. Quando número for fracionário, ou parte fracionária, a posição é negativa. Após somamos os produtos e teremos a representação do número na base dez. 

Algoritmo: 

$$
d_n⋅b^n+d_{n-1}⋅b^{n-1}+\cdots+d_0⋅b^0+d_{-1}⋅b^{-1}+d_{-2}⋅b^{-2}+\cdots
$$

Exemplo para: `101010,11`.

$$
\small
x = (101010,11)_2  \newline
x = (1*2^5)+(0*2^4)+(1*2^3)+(0*2^2)+(1*2^1)+(0*2^0)+(1*2^{-1}))+(1*2^{-2}) \newline
x = 32+0+8+0+2+0+0,5+0,25
x = 42,75
$$

## Prática de programação. Conversão de bases numéricas

### De uma base *n* para a base decimal

Agora vou trazer um exemplo de um código que converte um número em determinada base para decimal na linguagem C. 

```c
#include <stdio.h>

int  value_of(char ch);
int  base_from_to_decimal(char *nbr, int base_from);

int   main(void) {

  printf("42 to b10 = %d\n", base_from_to_decimal("42", 10));
  printf("2A to b10 = %d\n", base_from_to_decimal("2A", 16));
  printf("101010 to b10 = %d\n", base_from_to_decimal("101010", 2));
  printf("\n");

  return (0);
}

int   value_of(char ch) {
  if (ch >= '0' && ch <= '9')
    return (ch - '0');
  else if (ch >= 'a' && ch <= 'f')
    return (ch - 'a' + 10);
  else if (ch >= 'A' && ch <= 'F')
    return (ch - 'A' + 10);

  return (0);
}

int  base_from_to_decimal(char *nbr, int base_from)
{
  int   result;

  result = 0;
  while(*nbr)
	{
		result = result * base_from + value_of(*nbr);
		nbr++;
	}

  return (result);
}
```

O que interessa no código acima são as funções `value_of` e `base_from_to_decimal`.

A função `value_of` devolve o inteiro correspondente ao um caractere na tabela ASCII (American Standard Code for Information Interchange ou ”Código Padrão Americano para o Intercâmbio de Informação”).

Esse processo de recuperação é necessário pelo fato que a número a ser convertido é passado para a função `base_from_to_decimal` como uma cadeia de caracteres, mais comumente conhecido: uma *string*. 

A função `base_from_to_decimal` recebe dois parâmetros: a cadeia de caracteres que contém a representação do número a ser convertido para decimal e um inteiro indicando qual base ela está organizado. 

No corpo, declaramos e é inicializado uma variável, `result`, do tipo inteiro, que será retornada com o valor do número convertido de decimal. 

Em seguida realizamos uma interação sobre a ******string****** recebida. Para cada caractere recuperemos o seu valor decimal da tabela ASCII com a função `value_of`. Esse valor é somado ao produto do valor de `result`, a cada interação, multiplicado pela base de origem. 

Uma vez encerrado o ****loop**** a variável `result` é retornada com a representação do número na base dez. 

O código é uma implementação bem grosseira. Apenas como demonstração do conceito aqui estudado. Observar-se que esse código realiza apenas conversão de números inteiros.

### Da base decimal para uma base *n*

O código abaixo converte um número decimal para uma outra base desejada. 

```c
#include <stdio.h>
#define MAX_SIZE 32

void    to_base(int nbr, char *base, int len, char resulted[], int i)
{
    if (nbr/len != 0)
        to_base((nbr/len), base, 2, resulted, i);

    while (resulted[i] != '\0'&& i < MAX_SIZE)
        i++;
        
    resulted[i] = base[nbr%len];
}

int main(void) 
{
  char resulted[MAX_SIZE];
  int  nbr;
  int  i;

  nbr = 42;
  i= 0;
  if (nbr < 0)
  {
    sing++;
    resulted[0] = '-';
  }
  to_base(nbr, "01", 2, resulted, i);
  printf("%d to B2: %s\n", nbr, resulted);
  return (0);
}
```

Explicando rapidamente a função `main`. 

Nela é declarada um vetor de caracteres no qual será armazenado a representação do nosso número convertido. Em seguida é declarado a variável `nbr` , tipo inteiro, que será utilizada para definir o número que se deseja converter e o inteiro `i` que terá a função de definir o início do posicionamento dos caracteres. Pois, caso o número seja negativo, será necessário posicionar o sinal negativo no início do vetor. 

Logo, é feito um verificação se o número é negativo, se sim é realizado o procedimento descrito  acima. 

Feito isso, é realizada uma chamada para a função `to_base` que recebe cinco argumentos:

1. O número a ser convertido, do tipo inteiro: `nbr`;
2. A base desejada, do tipo cadeia de caracteres: `base`;
3. O tamanho da base, do tipo inteiro: `len`;
4. Um vetor de caracteres onde será salvo a representação numérica convertida: `resulted`;
5. E um inteiro, que serve com *index* para o o vetor: `i`.

A função `to_base` é recursiva. Ela chama a se mesma por quanto o valor de `nbr` for diferente de zero. E a cada nova chamada o valor de `nbr`é dividido por `len`. Lembrando que, a cada nova chamada da função, ela é empilhada na pilha com os valores atuais da chamada. Aqui não vou entrar nos detalhes de como é a execução de uma função recursiva. 

Quando o resultado da divisão for zero as chamadas recursivas se encerram e volta a continuar o fluxo de execução, da função, a partir de cada chamada. 

Outro ponto importante a lembrar: é que devemos alinhar os restos da divisão na ordem inversa que forem encontrados. Nesse caso, devemos salvar o resto da cada divisão a partir do resultado da última chamada da função até a primeira. Enquanto é desempilhada da pilha de chamadas. 

Continuando a explicação da função. 

No laço `while` seguinte, recortado do código da função `to_base` :

```c
while (resulted[i] != '\0' && i < MAX_SIZE)
        i++;
```

O valor de `i` que é incrementado até que seja encontrado um local no vetor `resulted` que possa receber o dígito, desde que seja respeitado o tamanho máximo disponível pelo vetor. 

Em seguida, o valor do digito resultante do módulo do valor presente de `nbr` por `len` é armazenado na vetor que representará o número convertido ao final. A posição é dada pelo valor de `i`.  

Imperar anotar que nos dois exemplos não é implementado uma forma de lidar com números fracionários, mas caso o leitor tenha interesse: [Neste artigo](https://www.exploringbinary.com/converting-floating-point-numbers-to-binary-strings-in-c/) o autor implementa um algoritmo que converte um número de ponto flutuante para uma ******string****** que representa o número na base `2`.