Ir para o conteúdo principal

Bases Numéricas e Conversão de Inteiros: O Guia Completo

Autor
Francisco Bustamante
Químico, cientista de dados e programador Python.
Tabela de conteúdos
Do Zero ao Float - Este artigo faz parte de uma série de artigos.
Parte 1: Esse Artigo

Sistemas computacionais não “entendem” números da mesma forma que nós. Em hardware, toda informação — instruções, endereços, caracteres e valores numéricos — precisa ser codificada em sinais elétricos com poucos estados estáveis. Por isso, a base conceitual da computação digital é o uso de sistemas de numeração, especialmente aqueles que se encaixam naturalmente na eletrônica e na organização de bits.

Na prática, você vai alternar entre representações dependendo do contexto: o binário é a linguagem nativa do circuito; o hexadecimal (e, historicamente, o octal) existem para tornar padrões de bits legíveis; e o decimal continua sendo o sistema mais conveniente para interação humana, leitura e verificação de resultados.

Neste artigo, você vai aprender:

  • o que é notação posicional e como ela funciona;
  • como converter números inteiros entre bases comuns (decimal, binário, octal e hexadecimal);
  • quando é possível acelerar conversões usando agrupamento/expansão de dígitos (bases relacionadas por potência).

O foco aqui é em números inteiros não negativos. Em artigos futuros, trataremos conversões com sinal (incluindo representação em complemento de dois) e números em ponto flutuante.

Algumas definições rápidas antes de começar:

  • Binário (base-2) é a base dos sistemas digitais: bits e operações lógicas trabalham diretamente com 0 e 1.
  • Hexadecimal (base-16) e Octal (base-8) são usados para compactar e “enxergar” sequências binárias sem perder correspondência com os bits.
  • O sistema Decimal (base-10) é o padrão do dia a dia e aparece naturalmente em entradas/saídas, documentação e validação manual.
  • Outros sistemas quase não aparecem em computação, mas deixaram herança no dia a dia: o Duodecimal (base-12) sobrevive na contagem por dúzias e grosas, nas 12 horas do mostrador do relógio e nas 12 polegadas de um pé; e o Sexagesimal (base-60), herdado dos babilônios, é a razão de um minuto ter 60 segundos e de um grau ter 60 minutos de arco.

Tipos de Sistema de Numeração
#

Um sistema de numeração é definido pela sua base (radix), que determina quantos símbolos existem e quais são os pesos de cada posição. A seguir estão os quatro sistemas mais frequentes em computação.

Antes de listá-los, vale um contraste que deixa a palavra “posicional” bem mais concreta. Todos os sistemas deste artigo são posicionais ponderados: o mesmo símbolo vale coisas diferentes conforme a posição que ocupa. Nem todo sistema de numeração funciona assim.

Sistema Como escreve 1989 Quanto vale o símbolo destacado
Decimal (posicional) 1989 900 — porque está na casa das centenas
Romano (não-posicional) MCMLXXXIX 50 — em qualquer lugar da sequência

No romano, L vale 50 esteja onde estiver, e o que altera o resultado é a ordem relativa entre os símbolos: em IX o I subtrai, em XI ele soma. No decimal, o mesmo 9 vale 900 numa posição e 9 em outra — é a posição que carrega o peso. Essa diferença é exatamente o que torna a aritmética posicional mecânica: somar dois números vira um procedimento de coluna, com vai-um, que funciona igual para 12 ou para 12 milhões.

De onde vem a notação que usamos

O sistema posicional de dez símbolos com um zero explícito nasceu na Índia por volta do século V, foi sistematizado por matemáticos como Brahmagupta (século VII) — que tratou o zero como número, e não apenas como espaço vazio — e chegou à Europa pelo mundo árabe, daí o nome sistema hindu-arábico. Sua popularização no Ocidente costuma ser creditada ao Liber Abaci (1202), de Leonardo de Pisa, o Fibonacci. O que o tornou superior ao romano não foram os símbolos, e sim o zero posicional: sem ele não dá para distinguir \(15\) de \(105\) sem inventar um espaço em branco, e sem essa distinção não existe algoritmo de coluna.

Sistema de Numeração Decimal
#

  • O sistema Decimal é um sistema de numeração de base 10.
  • Ele usa dez dígitos: 0, 1, 2, 3, 4, 5, 6, 7, 8 e 9.
  • O valor posicional de cada dígito é uma potência de 10 (por exemplo, \(10^{0}\), \(10^{1}\), \(10^{2}\)).
  • É o sistema padrão para contagem e cálculos do dia a dia.

Sistema de Numeração Binário
#

  • O sistema Binário é um sistema de numeração de base 2.
  • Ele usa dois dígitos: 0 e 1.
  • O valor posicional de cada dígito é uma potência de 2 (por exemplo, \(2^{0}\), \(2^{1}\), \(2^{2}\)).
  • O sistema Binário é a base para representação de dados em computadores e eletrônica digital.

Sistema de Numeração Octal
#

  • O sistema Octal é um sistema de numeração de base 8.
  • Ele usa oito dígitos: 0, 1, 2, 3, 4, 5, 6 e 7.
  • O valor posicional de cada dígito é uma potência de 8 (por exemplo, \(8^{0}\), \(8^{1}\), \(8^{2}\)).
  • Ele é frequentemente usado para simplificar a representação de números binários agrupando-os em conjuntos de três bits.

Sistema de Numeração Hexadecimal
#

  • O sistema Hexadecimal é um sistema de numeração de base 16.
  • Ele usa dezesseis símbolos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E e F.
  • Os símbolos A–F representam valores decimais de 10 a 15 (por exemplo, \(A = 10\), \(B = 11\), …, \(F = 15\)).
  • O valor posicional de cada dígito é uma potência de 16 (por exemplo, \(16^{0}\), \(16^{1}\), \(16^{2}\)).
  • O Hexadecimal simplifica o binário ao representar cada 4 bits como um dígito (0–F).
  • Usar as letras A–F não era óbvio nem foi consenso imediato: houve notações concorrentes até o padrão atual se firmar (Hexadecimal).

Resumindo:

Sistema (base) Símbolos disponíveis Valor posicional (pesos) Uso típico em computação Conversão rápida com binário (quando aplicável)
Decimal (10) 0–9 potências de 10: \(10^0,10^1,10^2,\dots\) Interação humana, leitura, documentação, validação manual de resultados
Binário (2) 0–1 potências de 2: \(2^0,2^1,2^2,\dots\) Representação nativa em hardware (bits), operações lógicas
Octal (8) 0–7 potências de 8: \(8^0,8^1,8^2,\dots\) Legibilidade/compactação de bits (contexto histórico e alguns sistemas) \(8=2^3\): 1 dígito octal ↔ 3 bits
Hexadecimal (16) 0–9, A–F (\(A=10,\dots,F=15\)) potências de 16: \(16^0,16^1,16^2,\dots\) Endereços, dumps de memória, padrões de bits legíveis (muito comum) \(16=2^4\): 1 dígito hex ↔ 4 bits

Vamos entender melhor o que queremos dizer com valor posicional.

Números inteiros e notação posicional
#

Como destacado anteriormente, este artigo foca em números inteiros e suas representações em diferentes bases. A notação posicional é o método mais comum para representar números em qualquer base: o valor de cada dígito depende de sua posição, e cada posição tem peso dado por uma potência da base.

Em termos práticos, essa ideia explica por que:

  • a expansão posicional permite transformar um número de qualquer base para decimal (somando pesos);
  • as divisões sucessivas “extraem” os dígitos do número na base desejada, do menos significativo para o mais significativo.

Um número \(N\) em uma base \(b\) pode ser representado como:

$$ N_b = \sum_{i=0}^{n} d_i \cdot b^i = d_n \cdot b^n + d_{n-1} \cdot b^{n-1} + ... + d_1 \cdot b^1 + d_0 \cdot b^0 $$

onde \(d_i\) são os dígitos do número e \(b\) é a base. Cada dígito \(d_i\) deve satisfazer \(0 \leq d_i < b\).

Repare numa consequência pequena dessa restrição, mas que costuma reorganizar o entendimento de quem está começando: como a base nunca está entre os símbolos disponíveis, o valor da própria base é sempre escrito 10, em qualquer base. Em binário, \(10_2 = 2\); em octal, \(10_8 = 8\); em hexadecimal, \(10_{16} = 16\). Ou seja, “10” não significa “dez”: significa “uma vez a base, mais zero unidades”.

Observação: a mesma lógica vale para a parte fracionária, usando potências negativas (\(b^{-1}, b^{-2}, ...\)). Como aqui o foco é em inteiros, voltaremos a frações e ponto flutuante em artigos específicos.

Por exemplo, o número \(123_{10}\) em base decimal pode ser expandido como:

$$ 123_{10} = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0 = 100 + 20 + 3 $$

A partir daqui, vamos usar neste artigo as seguintes notações para bases:

  • \(s\) como base de origem (s de source);
  • \(r\) como base de destino (r de result);
  • \(b\) apenas quando a base for genérica em uma fórmula.

Métodos de Conversão
#

Para converter números inteiros entre bases, não é necessário decorar dezenas de regras. Na verdade, precisamos dominar apenas dois métodos fundamentais, usando o sistema Decimal como uma “ponte” ou “tradutor universal”:

  1. Expansão Posicional (Multiplicação): Usado quando queremos descobrir quanto vale um número de qualquer base em Decimal.
  2. Divisões Sucessivas: Usado quando temos um valor em Decimal e queremos codificá-lo para outra base.

De qualquer base para Decimal (Expansão)
#

Quando você tem um número em binário, octal ou hexadecimal e quer saber o valor numérico dele (“quanto isso vale no meu dia a dia?”), você usa a Expansão Posicional.

O processo é simples: somar o valor de cada dígito multiplicado pelo peso da sua posição (a base elevada à potência da posição).

$$ N_{10} = \sum (\text{dígito} \times \text{base}^{\text{posição}}) $$
Exemplo: Converter \(1101_2\) para Decimal

Identificamos a base (\(2\)) e as posições (começando de 0 da direita para a esquerda).

$$ \begin{align*} 1101_2 & = 1 \cdot 2^3 + 1 \cdot 2^2 + 0 \cdot 2^1 + 1 \cdot 2^0 \\ & = 1 \cdot 8 + 1 \cdot 4 + 0 \cdot 2 + 1 \cdot 1 \\ & = 8 + 4 + 0 + 1 \\ & = 13_{10} \end{align*} $$

Dica de verificação: em binário, \(1101_2\) deve estar entre \(8_{10}\) (representado como \(1000_2\)) e \(16_{10}\) (representado como \(10000_2\)), então \(13_{10}\) faz sentido.

Essa mesma conta cabe numa figura, e vale olhar para ela mesmo que a expansão acima já tenha ficado clara — são dois caminhos para a mesma ideia. A régua abaixo põe o peso de cada posição logo acima do bit correspondente e, embaixo, a parcela que aquele bit contribui. O bit desligado aparece em cinza justamente porque não soma nada:

Régua posicional do número 1101 em binário. Acima de cada um dos quatro bits estão a posição e o peso correspondente: 2 elevado a 3 igual a 8, 2 ao quadrado igual a 4, 2 elevado a 1 igual a 2 e 2 elevado a 0 igual a 1. Abaixo de cada bit, uma seta aponta para a parcela que ele contribui: 8, 4, 0 e 1. A soma das parcelas resulta em 13 em decimal.
Os quatro bits de 1101 em binário com o peso de cada posição e a parcela correspondente. O bit desligado, em cinza, contribui com zero.

Exemplo: Converter \(2F_{16}\) para Decimal

Lembre-se que em Hexadecimal, \(F = 15\).

$$ \begin{align*} 2F_{16} & = 2 \cdot 16^1 + 15 \cdot 16^0 \\ & = 32 + 15 \\ & = 47_{10} \end{align*} $$

De Decimal para qualquer base (Divisões Sucessivas)
#

Quando você tem um número decimal e precisa representá-lo em binário, octal ou qualquer outra base, o método padrão é o das Divisões Sucessivas.

O algoritmo é:

  1. Divida o número decimal pela base de destino.
  2. Anote o resto (ele será um dos dígitos).
  3. Pegue o quociente e divida novamente pela base.
  4. Repita até que o quociente seja zero.
  5. O resultado é formado pelos restos lidos do último para o primeiro (de baixo para cima).
Exemplo: Converter \(45_{10}\) para Binário (Base 2)

$$ \begin{align*} 45 \div 2 & = 22 \quad & \text{resto } \mathbf{1} \\ 22 \div 2 & = 11 \quad & \text{resto } \mathbf{0} \\ 11 \div 2 & = 5 \quad & \text{resto } \mathbf{1} \\ 5 \div 2 & = 2 \quad & \text{resto } \mathbf{1} \\ 2 \div 2 & = 1 \quad & \text{resto } \mathbf{0} \\ 1 \div 2 & = 0 \quad & \text{resto } \mathbf{1} \end{align*} $$

Lendo de baixo para cima: \(101101_2\).

Dica de verificação: reconverta \(101101_2\) para decimal via expansão posicional e confira se volta em \(45_{10}\).

O Método da “Ponte Decimal” (Base \(A \to\) Base \(B\))
#

E se quisermos converter de Base 9 para Base 4? Ou de Base 5 para Base 7?

Como essas bases não conversam diretamente entre si, usamos o Decimal como intermediário. O processo tem duas etapas:

  1. Origem \(\to\) Decimal (usando Expansão).
  2. Decimal \(\to\) Destino (usando Divisões).
Exemplo: Converter \(87_9\) para Base 4

Passo 1: Base 9 para Decimal

$$ 87_9 = 8 \cdot 9^1 + 7 \cdot 9^0 = 72 + 7 = \mathbf{79_{10}} $$

Passo 2: Decimal (79) para Base 4

$$ \begin{align*} 79 \div 4 & = 19 \quad & \text{resto } \mathbf{3} \\ 19 \div 4 & = 4 \quad & \text{resto } \mathbf{3} \\ 4 \div 4 & = 1 \quad & \text{resto } \mathbf{0} \\ 1 \div 4 & = 0 \quad & \text{resto } \mathbf{1} \end{align*} $$

Lendo os restos de baixo para cima: \(1033_4\).

Logo, \(87_9 = 1033_4\).

Mais um exemplo:

Exemplo: Converter \(2F_{16}\) para base \(2\)
  1. Converter de hexadecimal para decimal. Note que \(F\) é um símbolo, não um número: antes de fazer qualquer conta, troque cada símbolo pelo valor que ele representa (aqui, \(F = 15\)): $$ 2F_{16} = 2 \times 16^1 + F \times 16^0 = 2 \times 16^1 + 15 \times 16^0 $$

Agora sim, com tudo em decimal:

$$ 2 \times 16 + 15 \times 1 = 32 + 15 = 47_{10} $$
  1. Converter de decimal para binário: $$ \begin{align*} 47 \div 2 & = 23 & \quad \text{resto } 1 \\ 23 \div 2 & = 11 & \quad \text{resto } 1 \\ 11 \div 2 & = 5 & \quad \text{resto } 1 \\ 5 \div 2 & = 2 & \quad \text{resto } 1 \\ 2 \div 2 & = 1 & \quad \text{resto } 0 \\ 1 \div 2 & = 0 & \quad \text{resto } 1 \end{align*} $$

Lendo de baixo para cima: \(2F_{16} = 101111_2\).

Dica de verificação: você pode conferir o resultado em hexadecimal agrupando \(101111_2\) em 4 bits com padding (preenchimento com zeros) à esquerda — \(0010\) e \(1111\), ou seja, \(2F_{16}\), que é de onde partimos.

Exemplo: Converter \(1101_2\) para hexadecimal (\(16\))
  1. Converter para decimal:

    $$ 1101_2 = 1 \times 2^3 + 1 \times 2^2 + 0 \times 2^1 + 1 \times 2^0 = 13_{10} $$
  2. Converter decimal para hexadecimal:

    $$ 13_{10} = D_{16} $$

Assim, \(1101_2 = D_{16}\).

Dica de verificação: como 4 bits formam 1 dígito hexadecimal, \(1101_2\) deve mesmo mapear para \(D_{16}\).

Estes dois últimos casos em específico podem ser simplificado, sem ter que passar por decimal, pois \(16 = 2^4\). Assim, cada dígito hexadecimal corresponde exatamente a 4 bits binários. Veja a seção Facilitando a Conversão Quando as Bases São Relacionadas por Potência para mais detalhes. Mas a abordagem “via decimal” funciona para qualquer par de bases.

Resumo Geral dos Métodos
#

Objetivo Método
Descobrir o valor (Qualquer \(\to\) Decimal) Expansão Posicional (Soma das multiplicações)
Codificar o valor (Decimal \(\to\) Qualquer) Divisões Sucessivas (Ler restos de baixo para cima)
Troca de representação (Base \(A \to\) Base \(B\)) Ponte via Decimal (Expansão \(\to\) Divisão)

Erros comuns (e como evitar)
#

  • Ler restos na ordem errada: em divisões sucessivas, o resultado é lido de baixo para cima.
  • Esquecer a base no subíndice: sempre mantenha a notação (\(N_s\) e \(N_r\)) para não misturar interpretações.
  • No agrupamento (binário→octal/hex), agrupar a partir da direita; se faltar bits no grupo mais à esquerda, completar com zeros (padding).
  • No “via decimal”, esquecer de converter símbolos como \(A\)–\(F\) para valores \(10\)–\(15\).

Facilitando a Conversão Quando as Bases São Relacionadas por Potência
#

Se \(s\) e \(r\) possuem uma relação de potência (\(s = r^k\) ou \(r = s^k\)), você pode converter diretamente agrupando ou expandindo dígitos, sem fazer contas longas.

A regra prática mais comum em computação é:

  • se você está indo do binário para uma base maior, agrupe bits;
  • se você está indo de uma base maior para o binário, expanda cada dígito para bits.

Caso 1: Base Menor para Base Maior (\(s < r\))
#

Se \(r = s^k\), cada dígito em base \(r\) corresponde exatamente a \(k\) dígitos na base \(s\). Em computação, o caso clássico é \(s=2\) e \(r \in \{8,16\}\), onde:

  • \(8 = 2^3\) (logo \(k=3\));
  • \(16 = 2^4\) (logo \(k=4\)).
Exemplo: Conversão de Binário (\(2\)) para Octal (\(8\))

Sabemos que \(8 = 2^3\), então cada grupo de 3 bits representa um dígito octal.

Passo 1: Separar o número binário em blocos de 3 bits da direita para a esquerda

$$ 101011_2 $$

Agrupamos:

$$ \mathbf{101} \quad \mathbf{011} $$

Passo 2: Converter cada grupo para octal

$$ 101_2 = 5_8, \quad 011_2 = 3_8 $$

Resultado final:

$$ 101011_2 = 53_8 $$
Exemplo: Conversão de Binário (\(2\)) para Hexadecimal (\(16\))

Como \(16 = 2^4\), agrupamos os dígitos de 4 em 4.

Passo 1: Separar o número binário em blocos de 4 bits

$$ 11010101_2 $$

Agrupamos:

$$ \mathbf{1101} \quad \mathbf{0101} $$

Passo 2: Converter cada grupo para hexadecimal

$$ 1101_2 = D_{16}, \quad 0101_2 = 5_{16} $$

Resultado final:

$$ 11010101_2 = D5_{16} $$

O passo a passo acima fica ainda mais direto quando visto de uma vez só. Na figura, os dois blocos de 4 bits aparecem lado a lado, cada um com a soma dos pesos que produz o seu dígito hexadecimal — e os dois dígitos se juntam no resultado final, na mesma ordem em que os blocos estavam:

Agrupamento do número 11010101 em binário para hexadecimal. Os oito bits são separados em dois blocos de quatro: o bloco 1101, em azul, soma 8 mais 4 mais 1 igual a 13, que é o dígito D em hexadecimal; o bloco 0101, em verde, soma 4 mais 1 igual a 5, que é o dígito 5. Os dois dígitos se juntam no resultado D5 em hexadecimal.
Cada bloco de 4 bits vira um dígito hexadecimal, e os dígitos são colados na mesma ordem dos blocos.

Exemplo com outras bases:

Exemplo: Converter \(2120_{3}\) para base \(9\)

Como \(9 = 3^{2}\), cada dígito em base \(9\) corresponde a um bloco de 2 dígitos em base \(3\).

Passo 1: Agrupar os dígitos de 2 em 2, da direita para a esquerda:

$$ 2120_{3} \quad \Rightarrow \quad \mathbf{21} \quad \mathbf{20} $$

Passo 2: Converter cada bloco (em base \(3\)) para um dígito (em base \(9\)):

$$ \begin{align*} 21_{3} & = 2\cdot 3^{1} + 1\cdot 3^{0} = 6 + 1 = 7_{10} = 7_{9} \\ 20_{3} & = 2\cdot 3^{1} + 0\cdot 3^{0} = 6 + 0 = 6_{10} = 6_{9} \end{align*} $$

Resultado final: \(2120_{3} = 76_{9}\)

Caso 2: Base Maior para Base Menor (\(s > r\))
#

Se \(s = r^k\), você pode expandir cada dígito da base maior em \(k\) dígitos da base menor. Em computação, novamente o caso mais comum é expandir octal/hexadecimal para binário.

Exemplo: Conversão de Octal (\(8\)) para Binário (\(2\))

Como \(8 = 2^3\), cada dígito octal pode ser escrito como 3 dígitos binários.

Passo 1: Substituir cada dígito octal por sua forma binária de 3 bits

$$ 753_8 $$

Expandimos:

$$ 7_8 = 111_2, \quad 5_8 = 101_2, \quad 3_8 = 011_2 $$

Resultado final:

$$ 753_8 = 111101011_2 $$
Exemplo: Conversão de Hexadecimal (\(16\)) para Binário (\(2\))

Como \(16 = 2^4\), cada dígito hexadecimal pode ser escrito como 4 dígitos binários.

Passo 1: Substituir cada dígito hexadecimal por sua forma binária de 4 bits

$$ 4F2_{16} $$

Expandimos:

$$ 4_{16} = 0100_2, \quad F_{16} = 1111_2, \quad 2_{16} = 0010_2 $$

Resultado final:

$$ 4F2_{16} = 010011110010_2 $$

Resumo das estratégias quando as bases são relacionadas por potência
#

Conversão Método Simplificado
Binário \(\to\) Octal (\(2 \to 8\)) Agrupar em blocos de 3 bits
Binário \(\to\) Hexadecimal (\(2 \to 16\)) Agrupar em blocos de 4 bits
Octal \(\to\) Binário (\(8 \to 2\)) Expandir cada dígito octal em 3 bits
Hexadecimal \(\to\) Binário (\(16 \to 2\)) Expandir cada dígito hexadecimal em 4 bits

Fluxograma de Escolha de Método
#

Para facilitar a escolha do método adequado para conversão entre bases, aqui está um fluxograma resumido:

flowchart TD
    Start([Converter da base s
para base r]) --> CheckDest{r = 10?} %% Caso 1: Destino é Decimal CheckDest -- Sim --> Method1[Método 1: Expansão Posicional
Multiplicar cada dígito pelo
peso da sua posição] Method1 --> Result([Resultado em Decimal]) %% Caso 2: Origem é Decimal CheckDest -- Não --> CheckOrig{s = 10?} CheckOrig -- Sim --> Method2[Método 2: Divisões Sucessivas
Dividir N sucessivamente por r
e ler os restos de baixo para cima] Method2 --> Result2([Resultado na Base r]) %% Caso 3: Bases Arbitrárias (Ponte ou Atalho) CheckOrig -- Não --> CheckPower{sk = r?
Ou rk = s?
Ex: 2, 8, 16} %% Atalho CheckPower -- Sim --> Method3a[Atalho: Agrupamento ou Expansão
Substituir dígitos por bits ou
agrupar bits em dígitos] Method3a --> Result2 %% Ponte Decimal CheckPower -- Não --> Method3b[Método 3: Ponte Decimal
1. Converter s para 10 Expansão
2. Converter 10 para r Divisão] Method3b --> Result2 %% Estilização para ficar bonito no blog style Start fill:#f9f,stroke:#333,stroke-width:2px,color:black style Result fill:#ccf,stroke:#333,stroke-width:2px,color:black style Result2 fill:#ccf,stroke:#333,stroke-width:2px,color:black style Method1 fill:#e1f7d5,stroke:#333,color:black style Method2 fill:#e1f7d5,stroke:#333,color:black style Method3a fill:#fff4e6,stroke:#f66,stroke-width:2px,stroke-dasharray: 5 5,color:black style Method3b fill:#e1f7d5,stroke:#333,color:black

Explicação visual das cores usadas no gráfico:

  • Verde claro: Os métodos “padrão” (algoritmos matemáticos).
  • Laranja/Tracejado: O atalho (um caminho especial).
  • Roxo: Pontos de início e fim.

Representação Prática: Bases Numéricas em Python
#

Na matemática, usamos subíndices (como \(101_2\) ou \(75_{16}\)) para indicar a base. No entanto, na hora de programar, não temos como digitar subíndices facilmente. Por isso, linguagens de programação adotam prefixos para indicar ao interpretador em qual base o número está escrito.

Como o Python é a linguagem principal abordada neste site, veja como representar e manipular essas bases nativamente:

Literais (Escrevendo números no código)
#

Para escrever um número inteiro diretamente em uma base específica, usamos o dígito 0 seguido de uma letra identificadora:

  • Binário: Prefixo 0b (Ex: 0b1010)
  • Octal: Prefixo 0o (Ex: 0o52)
  • Hexadecimal: Prefixo 0x (Ex: 0x2F)

Ao digitar esses valores, o Python os interpreta e armazena internamente como inteiros normais.

# O Python entende todos estes valores como o mesmo número (42)
n_dec = 42
n_bin = 0b101010
n_oct = 0o52
n_hex = 0x2A

print(n_dec == n_bin == n_oct == n_hex) # Saída: True
print(n_hex) # Saída: 42 (O print padrão sempre mostra em decimal)

Funções de Conversão
#

Se você precisa converter um número para uma string formatada em outra base, ou converter uma string para um inteiro, use as funções nativas:

Função Descrição Exemplo Entrada Exemplo Saída
bin(x) Converte inteiro para string binária bin(10) '0b1010'
oct(x) Converte inteiro para string octal oct(10) '0o12'
hex(x) Converte inteiro para string hexadecimal hex(10) '0xa'
int(s, base) Converte string de base (b) para inteiro int('101', 2) 5

Observações úteis:

  • int(s, base) aceita bases de 2 a 36, além de base=0, que detecta a base pelo prefixo (0b, 0o, 0x) e trata a string como um literal Python.
  • Com base explícita, o prefixo é aceito desde que combine com a base: int('0b101', 2) devolve 5, int('0o52', 8) devolve 42 e int('0x1A', 16) devolve 26. O que falha é a contradição entre prefixo e base: int('0b101', 10) levanta ValueError.
  • Há uma armadilha divertida nessa regra: int('0b101', 16) não dá erro nem vale 5 — devolve 45313, porque em base 16 0b101 não é prefixo coisa nenhuma, é um numeral hexadecimal perfeitamente válido (\(\mathtt{0B101}_{16}\)).
  • Com base=0, os literais seguem as regras do Python: int('101', 0) é 101, mas int('010', 0) levanta ValueError — zeros à esquerda não são permitidos.

Exemplo prático de uso:

valor = 255

# Formatando para visualização (usando f-strings modernas)
# :b para binário, :o para octal, :x para hex minúsculo, :X para hex maiúsculo
# Use # para incluir o prefixo (0b, 0o, 0x) na saída: {valor:#b}, {valor:#x}, etc.
print(f"Decimal: {valor}")      # 255
print(f"Binário: {valor:b}")    # 11111111
print(f"Octal:   {valor:o}")    # 377
print(f"Hex:     {valor:X}")    # FF
print(f"Hex c/ prefixo: {valor:#x}")  # 0xff

# Lendo entrada do usuário (que sempre vem como string)
entrada_usuario = "1A"
numero = int(entrada_usuario, 16)
print(numero) # Imprime 26

Exercício de Algoritmos: Implementando “Na Mão”
#

Embora as funções nativas do Python (int(), bin(), etc.) sejam altamente otimizadas e devam ser usadas em código de produção, implementar esses conversores do zero é um excelente exercício de lógica de programação para entender o que acontece “por baixo do capô”.

Abaixo, apresentamos implementações didáticas dos métodos de Expansão Posicional e Divisões Sucessivas.

Atenção

Este código é puramente educacional. Em projetos reais, sempre prefira as funções nativas da linguagem, que são escritas em C e muito mais rápidas.

# Mapeamento para dígitos maiores que 9 (A=10, B=11, etc.)
DIGITOS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

def qualquer_base_para_decimal(numero_str: str, base_origem: int) -> int:
    """
    Implementa o método da Expansão Posicional.
    Converte uma string numérica de base_origem para inteiro (decimal).
    """
    resultado_decimal = 0
    # Invertemos a string para começar da potência 0 (direita para esquerda)
    # Ex: "101" invertido vira "101" -> índices 0, 1, 2 correspondem a 2^0, 2^1, 2^2
    numero_invertido = numero_str[::-1].upper()
    
    for posicao, digito_char in enumerate(numero_invertido):
        # Valida ANTES de procurar: um caractere fora do alfabeto (ex: '#') faria
        # DIGITOS.index() estourar com uma mensagem que não ajuda ninguém
        if digito_char not in DIGITOS:
            raise ValueError(f"Caractere {digito_char} não é um dígito válido")

        # Descobre o valor numérico do caractere (ex: 'A' -> 10)
        valor_digito = DIGITOS.index(digito_char)
        
        if valor_digito >= base_origem:
            raise ValueError(f"Dígito {digito_char} inválido para base {base_origem}")
            
        # Acumula: dígito * (base ^ posição)
        resultado_decimal += valor_digito * (base_origem ** posicao)
        
    return resultado_decimal

def decimal_para_qualquer_base(numero_dec: int, base_destino: int) -> str:
    """
    Implementa o método das Divisões Sucessivas.
    Converte um inteiro (decimal) para uma string na base_destino.
    """
    if numero_dec == 0:
        return "0"
    
    restos = []
    dividendo = numero_dec
    
    while dividendo > 0:
        # Pega o resto da divisão
        resto = dividendo % base_destino
        
        # Pega o quociente para a próxima iteração
        dividendo = dividendo // base_destino
        
        # Converte o resto num caractere (ex: 15 -> 'F') e guarda
        restos.append(DIGITOS[resto])
    
    # O algoritmo exige ler os restos de baixo para cima (do último para o primeiro)
    return "".join(restos[::-1])

# --- Testando as funções ---

# Teste 1: Binário para Decimal (Expansão)
binario = "1101"
dec = qualquer_base_para_decimal(binario, 2)
print(f"Expansão: {binario}_2 para decimal é {dec}")
# Saída: Expansão: 1101_2 para decimal é 13

# Teste 2: Decimal para Hexadecimal (Divisão)
decimal = 47
hexa = decimal_para_qualquer_base(decimal, 16)
print(f"Divisão: {decimal}_10 para hexa é {hexa}")
# Saída: Divisão: 47_10 para hexa é 2F

# Teste 3: A Ponte (Base 9 para Base 4)
# Usamos o decimal como intermediário
valor_base9 = "87"
passo1_decimal = qualquer_base_para_decimal(valor_base9, 9)
passo2_base4 = decimal_para_qualquer_base(passo1_decimal, 4)
print(f"Conversão: {valor_base9}_9 -> {passo1_decimal}_10 -> {passo2_base4}_4")
# Saída: Conversão: 87_9 -> 79_10 -> 1033_4

Tabela-Resumo
#

Tudo o que este artigo estabeleceu, em uma página só:

Ideia Regra Exemplo do artigo
Notação posicional \(N_b = \sum_i d_i \cdot b^i\) \(1101_2 = 8 + 4 + 0 + 1 = 13_{10}\)
Dígitos válidos \(0 \leq d_i < b\) em base 9 não existe o dígito 9
A própria base escrita sempre como 10 \(10_2 = 2\), \(10_8 = 8\), \(10_{16} = 16\)
Qualquer base \(\to\) decimal expansão posicional \(2F_{16} = 2 \times 16 + 15 = 47_{10}\)
Decimal \(\to\) qualquer base divisões sucessivas, restos de baixo para cima \(45_{10} = 101101_2\)
Base \(s \to\) base \(r\) ponte via decimal \(87_9 = 79_{10} = 1033_4\)
Binário \(\to\) base \(2^k\) agrupar \(k\) bits, da direita para a esquerda \(101011_2 = 53_8\) (\(k = 3\))
Base \(2^k \to\) binário expandir cada dígito em \(k\) bits \(4F2_{16} = 010011110010_2\) (\(k = 4\))
Padding completar com zeros só à esquerda \(101111_2 \to 0010 1111\)
Verificação reconverter e comparar com o original \(13_{10} \to D_{16} \to 13_{10}\)
Em Python bin, oct, hex, int(s, base) int('2F', 16) devolve 47

Próximos passos
#

Neste ponto, você já tem duas ferramentas essenciais: (1) a expansão posicional, que permite interpretar um número em qualquer base, e (2) as divisões sucessivas, que permitem construir a representação em outra base. Além disso, quando as bases são relacionadas por potência (como \(2 \leftrightarrow 8\) e \(2 \leftrightarrow 16\)), você pode converter quase “de cabeça” usando agrupamento e expansão.

Se você quiser consolidar de verdade, pratique com a regra de ouro: sempre valide o resultado fazendo a conversão inversa. Comece com poucos exercícios (por exemplo, 5 conversões em cada direção) e tente alternar os métodos: em um dia, use expansão posicional; no outro, use divisões sucessivas; depois, use apenas agrupamento/expansão quando couber.

Nos próximos artigos, a ideia é avançar pelos temas que aparecem o tempo todo em Ciência da Computação. Primeiro, veremos como o hardware realiza operações aritméticas — soma e subtração — em qualquer base. Em seguida, entenderemos como representar inteiros com sinal (incluindo o Complemento de Dois) e como lidar com os limites da memória (Overflow). Por fim, mergulharemos nos números reais e na representação em ponto flutuante. Esses tópicos explicam, por exemplo, por que existem overflow, underflow e diferenças sutis entre “o número” e “o que cabe no registrador”.

Se você quiser, deixe nos comentários quais conversões você mais erra (decimal↔binário, binário↔hex, etc.) e eu incluo uma seção curta de “erros comuns + checagens rápidas” com exemplos adicionais.

Até a próxima!

Do Zero ao Float - Este artigo faz parte de uma série de artigos.
Parte 1: Esse Artigo

Relacionados

Lógica para programadores

·4116 palavras·20 minutos
Em programação, a palavra “lógica” pode se referir ou ao processo de elaboração de um algoritmo, ou a estruturas condicionais da linguagem, ou a operadores lógicos como E e OU. Nos dois últimos casos, estamos dentro da chamada lógica matemática.