No artigo anterior, aprendemos como ler e escrever números em diferentes bases, como o binário e o hexadecimal. Agora, vamos dar vida a esses números. Afinal, computadores não apenas armazenam dados; eles os processam.
A boa notícia é que você não precisa reaprender matemática. As regras de soma e subtração que você aprendeu no ensino fundamental para a base decimal (base 10) são universais. O conceito de “vai-um” (carry) ou de “pegar emprestado” funciona exatamente da mesma maneira, quer você esteja contando maçãs (decimal) ou pulsos elétricos (binário).
Neste artigo, vamos revisitar essas operações fundamentais na base 10 para isolar o algoritmo e, em seguida, aplicar exatamente a mesma lógica para realizar cálculos como um computador.
Base decimal #
A base decimal, também conhecida como base 10, é o sistema numérico mais utilizado no dia a dia. Ele é composto pelos dígitos de 0 a 9 e utiliza um sistema posicional, onde o valor de cada dígito depende de sua posição dentro do número.
Soma na base decimal - regra prática #
A soma de números decimais segue um processo posicional, onde os dígitos são somados coluna por coluna, começando pela unidade (direita) e avançando para a esquerda.
O “segredo” aqui é generalizar a regra: o “vai-um” ocorre sempre que a soma atinge ou ultrapassa o valor da Base. No caso decimal, se deu 10 ou mais, vai um.
Exemplo: Soma \(67 + 84\) na base 10
Passo a passo:
- Somamos a coluna das unidades: \(7 + 4 = 11\). Como o resultado tem dois dígitos (passou da base), colocamos o 1 na posição das unidades e levamos o outro 1 para a próxima coluna (chamado de “vai-um”).
- Somamos a coluna das dezenas: \(6 + 8 = 14\) e somamos o “vai-um”, ficando \(14 + 1 = 15\). Como não há mais colunas, o 15 é colocado como resultado final.
Portanto, o resultado da soma é 151.
O Movimento Vai-Um (Carry) #
O “vai-um” ocorre quando a soma de dois dígitos resulta em um valor maior que 9, já que 10 é a base do sistema decimal e o “vai-um” ocorre sempre que a soma atinge ou ultrapassa a base, como já vimos. Nesse caso, mantemos o dígito das unidades na coluna correspondente e levamos o dígito das dezenas para a próxima coluna.
Exemplo: Soma \(489 + 276\) na base 10
- Unidades: \(9 + 6 = 15\), escrevemos o 5 e levamos 1 para a coluna das dezenas.
- Dezenas: \(8 + 7 = 15\), somamos o “vai-um” (\(15 + 1 = 16\)), escrevemos 6 e levamos 1 para a próxima coluna.
- Centenas: \(4 + 2 = 6\), somamos o “vai-um” (\(6 + 1 = 7\)), resultando em 7.
O resultado final é 765.
Soma na base decimal - algoritmo formal #
A soma de números decimais segue um processo posicional, como vimos. Para entender melhor como isso funcionará em outras bases, vamos analisar o algoritmo formal: somamos a coluna e verificamos o resultado.
Se o valor for maior ou igual à base (neste caso, 10), não podemos representá-lo com um único dígito. Por isso, subtraímos o valor da base (10 no caso) para encontrar o que fica na coluna atual e, em troca, enviamos 1 para a próxima coluna (o carry ou “vai-um”).
Vamos repetir o exemplo anterior, mas agora detalhando o algoritmo formalmente.
Exemplo: Soma \(67 + 84\) na base 10 (Algoritmo Formal)
Passo a passo pelo algoritmo:
- Unidades: \(7 + 4 = 11\). Como \(11 \ge 10\), fazemos \(11 - 10 = 1\). O 1 fica e geramos um “vai-um”.
- Dezenas: \(6 + 8 = 14\). Somamos o “vai-um” (\(15\)). Como \(15 \ge 10\), fazemos \(15 - 10 = 5\). O 5 fica e geramos um “vai-um” para a próxima coluna (centenas).
Subtração na Base Decimal - Regra Prática #
A subtração também segue um processo posicional. Neste artigo, adotaremos o método conhecido como “carry sub” (ou método da compensação/adições iguais).
Sempre que for preciso “emprestar”, ao invés de diminuir o valor do topo, nós adicionamos 1 na casa imediatamente superior do subtraendo (o número de baixo). Isso mantém a diferença correta, mas deixa o visual da conta mais limpo.
Talvez você tenha aprendido na escola o método de “pedir emprestado” riscando o número de cima (ex: o 7 vira 6 para emprestar 1 para o 5). Ambos os métodos são matematicamente equivalentes. Usaremos o método da compensação aqui porque ele facilita a organização visual em algoritmos computacionais.
Exemplo: Subtração \(75 - 38\) (carry sub)
Passo a passo:
- Unidades: \(5 - 8\) não é possível. Para contornar isso, somamos 10 ao minuendo na casa das unidades (o \(5\) vira 15) e acrescentamos 1 à casa das dezenas do subtraendo (o \(3\) vira 4). Assim, a diferença permanece inalterada.
- Agora subtraímos as unidades: \(15 - 8 = 7\).
- Dezenas: após o ajuste (o 3 virou 4), subtraímos \(7 - 4 = 3\).
No final, obtemos \(37\) como resultado.
O Processo de Pegar Emprestado - carry sub #
No método “carry sub”, sempre que a casa superior não for suficiente para a subtração, adicionamos 10 (valor da base) ao algarismo do minuendo nessa casa e, simultaneamente, acrescentamos 1 à casa imediata do subtraendo.
Exemplo: Subtração \(402 - 189\) (carry sub)
- Unidades: precisamos fazer \(2 - 9\). Como \(2 < 9\), somamos 10 ao 2 (fica 12) e adicionamos 1 à casa das dezenas do subtraendo (8 vira 9). Agora subtraímos: \(12 - 9 = 3\).
- Dezenas: temos agora \(0 - 9\). Novamente não é possível sem “carregar”: somamos 10 ao 0 (vira 10) e acrescentamos 1 à casa das centenas do subtraendo (1 vira 2). Então fazemos \(10 - 9 = 1\).
- Centenas: restou \(4 - 2\), que é \(2\).
Dessa forma, obtemos o resultado \(213\).
Subtração na Base Decimal - Algoritmo Formal #
A subtração também segue um processo posicional. No método de compensação (carry sub), a lógica algorítmica é clara: se o dígito de cima é menor que o de baixo, somamos o valor da base (10 no caso) ao dígito de cima para tornar a subtração possível.
Para manter a equação equilibrada, devemos compensar adicionando 1 à próxima coluna do número de baixo (subtraendo).
Exemplo: Subtração \(75 - 38\) na base 10 (Algoritmo Formal)
Passo a passo pelo algoritmo:
- Unidades: \(5 - 8\) não é possível. Somamos a base ao 5 (\(5 + 10 = 15\)). Agora fazemos \(15 - 8 = 7\). Compensamos adicionando \(+1\) ao vizinho de baixo (o 3).
- Dezenas: Agora temos \(7\) em cima e \(3 + 1 = 4\) em baixo. Fazemos \(7 - 4 = 3\).
Outras bases #
Soma em diferentes bases #
A soma em bases diferentes segue o mesmo princípio da base decimal, o “vai-um” ocorre sempre que o resultado de uma soma ultrapassa o maior valor permitido na base. Agora, o algoritmo formal fica mais evidente: se o valor da soma é maior ou igual à base, subtraímos o valor da base para encontrar o que fica na coluna atual e enviamos 1 para a próxima coluna.
Vamos aos exemplos práticos:
Exemplo: Soma na base 9
A base 9 tem dígitos de 0 a 8. Sempre que a soma é maior ou igual à base (9), o “vai-um” é adicionado à próxima coluna.
$$ \begin{array}{c c c c} {\scriptscriptstyle 1} & \scriptscriptstyle 1 & & {} \\ {} & 6 & 7 & {} \\ {} + & 8 & 4 & {} \\ \hline 1 & (15) & (11) & {} \\ {} - & 9 & 9 & {\text{ subtraindo a base}} \\ \hline 1 & 6 & 2 & {} \end{array} $$Passo a passo:
- Unidades: \(7 + 4 = 11\). Escrevemos 2, resultado de \(11 - 9\) (base), e levamos 1 para a próxima coluna.
- Dezenas: \(6 + 8 = 14\). Somamos o “vai-um” e temos \(14 + 1 = 15\). O resultado é 6 e levamos 1 para a próxima coluna.
Portanto, o resultado da soma \(67 + 84\) na base 9 é \(162_9\).
Exemplo: Soma na base 16
A base 16 tem dígitos de 0 a F (representando 15). Sempre que a soma é maior ou igual à base (16), o “vai-um” é adicionado à próxima coluna. Resultado: \(F1A + E09 = 1D23_{16}\).
$$ \begin{array}{c c c c c} {\scriptscriptstyle 1} & & \scriptscriptstyle 1 & & {} \\ {} & F & 1 & A & {} \\ {} + & E & 0 & 9 & {} \\ \hline 1 & (29) & 2 & (19) & {} \\ {} - & 16 & & 16 & {\text{ subtraindo a base}} \\ \hline 1 & D & 2 & 3 & {} \end{array} $$Resultado: \(\mathtt{F1A} + \mathtt{E09} = \mathtt{1D23_{16}}\).
Antes de ver os exemplos em base 2, vale a pena ter em mente a “tabuada” básica da soma binária, que é onde a maioria das confusões acontece:
- \(0 + 0 = 0\)
- \(0 + 1 = 1\)
- \(1 + 0 = 1\)
- \(1 + 1 = 10_2\) (Fica 0 e vai 1)
- \(1 + 1 + 1 = 11_2\) (Fica 1 e vai 1)
Exemplo: Soma na base 2
A base 2 tem dígitos 0 e 1. Sempre que a soma é maior ou igual à base (2), o “vai-um” é adicionado à próxima coluna.
$$ \begin{array}{c c c c c c c} \scriptscriptstyle 1 & \scriptscriptstyle 1 & \scriptscriptstyle 1 & \scriptscriptstyle 1 & \scriptscriptstyle 1 & & {} \\ {} & 1 & 0 & 1 & 1 & 1 & {} \\ {} + & 1 & 1 & 0 & 1 & 1 & {} \\ \hline & (3) & (2) & (2) & (3) & (2) & {} \\ {} - & 2 & 2 & 2 & 2 & 2 & {\text{ subtraindo a base}} \\ \hline 1 & 1 & 0 & 0 & 1 & 0 & {} \end{array} $$Resultado: \(10111_2 + 11011_2 = 110010_2\).
Na base 2, vimos que \(1_2 + 1_2 = 10_2\) e \(1_2 + 1_2 + 1_2 = 11_2\). Assim, pode ser mais fácil somar números binários se lembrarmos dessas contas de cabeça.
Exemplo: Soma na base 2 usando conhecimento dos valores de 2 e 3 na base
Subtração em diferentes bases #
A subtração em bases diferentes segue o mesmo princípio que vimos na base decimal (carry sub/compensação): se o dígito de cima for menor que o de baixo, somamos a base ao de cima e compensamos somando 1 ao vizinho de baixo.
Novamente, o algoritmo formal fica mais evidente: se o valor da subtração é negativo, somamos o valor da base ao dígito de cima para tornar a subtração possível e adicionamos 1 à próxima coluna do número de baixo (subtraendo) para manter a equação equilibrada.
Exemplo: Subtração na base 8
Na base 8, os dígitos vão de 0 a 7. Sempre que a subtração resulta em um número negativo, emprestamos 1 da próxima coluna.
$$ \begin{array}{c c c} {} & 5 & 2^{\scriptscriptstyle+8} \\ {} - & 1^{\scriptscriptstyle+1} & 7 \\ \hline {} & 3 & 3 \end{array} $$
Exemplo: Subtração na base 16
Na base 16, os dígitos vão de 0 a F. Sempre que a subtração resulta em um número negativo, emprestamos 1 da próxima coluna.
$$ \begin{array}{c c c} {} & 5 & 2^{\scriptscriptstyle+16} \\ {} - & 1^{\scriptscriptstyle+1} & 7 \\ \hline {} & 3 & B \end{array} $$Na base 2, podemos usar o conhecimento já adquirido da “tabuada” para facilitar a subtração.
Exemplo: Subtração na base 2
Algoritmos Formais e Implementação #
Para um cientista da computação, entender a aritmética não é apenas saber fazer a conta no papel, mas entender o algoritmo que pode ser programado. Abaixo, apresentamos a lógica generalizada para qualquer Base \(B\), primeiro em pseudocódigo e depois em Python.
1. Algoritmo de Soma (Generalizado) #
A lógica central depende de duas operações inteiras: o resto da divisão (%)
determina o dígito que fica, e a divisão inteira (//) determina o “vai-um”.
Para começar, vamos ver em pseudocógido, que é uma forma de escrever algoritmos de maneira independente de linguagem de programação. Talvez facilite a compreensão antes de vermos o código Python.
Pseudocódigo:
FUNÇÃO Somar(Numero_A, Numero_B, BASE):
vai_um = 0
resultado = ""
PARA cada posição i (da direita para a esquerda):
soma_parcial = digito_a + digito_b + vai_um
# O dígito que fica é o resto da divisão pela base
digito_que_fica = soma_parcial MOD BASE
# O "vai-um" é a divisão inteira pela base
vai_um = soma_parcial DIV BASE
ADICIONAR digito_que_fica À ESQUERDA de resultado
SE vai_um > 0: ADICIONAR vai_um À ESQUERDA de resultado
RETORNAR resultadoImplementação em Python:
Para os códigos Python, usaremos uma string auxiliar para mapear dígitos maiores
que 9:
DIGITOS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
DIGITOS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def somar_bases(n1: str, n2: str, base: int) -> str:
# Inverte as strings para facilitar a iteração da direita para esquerda
n1, n2 = n1[::-1].upper(), n2[::-1].upper()
# Iguala o tamanho das strings com zeros à direita (que são à esquerda no número real)
tam_max = max(len(n1), len(n2))
n1 = n1.ljust(tam_max, '0')
n2 = n2.ljust(tam_max, '0')
vai_um = 0
resultado = []
for i in range(tam_max):
# Converte caractere para valor numérico (Ex: 'A' -> 10)
v1 = DIGITOS.index(n1[i])
v2 = DIGITOS.index(n2[i])
soma_parcial = v1 + v2 + vai_um
# Lógica da Base
digito_fica = soma_parcial % base
vai_um = soma_parcial // base
resultado.append(DIGITOS[digito_fica])
if vai_um > 0:
resultado.append(DIGITOS[vai_um])
# Inverte de volta para retornar a string correta
return "".join(resultado[::-1])
# --- Exemplos de Execução (Baseados nos exemplos do artigo) ---
# Base 10: 67 + 84
print(f"Base 10: {somar_bases('67', '84', 10)}")
# Resultado: 151
# Base 9: 67 + 84
print(f"Base 9: {somar_bases('67', '84', 9)}")
# Resultado: 162 (Note que 7+4=11, que é 12 na base 9)
# Base 16: F1A + E09
print(f"Base 16: {somar_bases('F1A', 'E09', 16)}")
# Resultado: 1D23
# Base 2: 10111 + 11011
print(f"Base 2: {somar_bases('10111', '11011', 2)}")
# Resultado: 1100102. Algoritmo de Subtração (Método Carry Sub) #
Neste método, quando o dígito de cima é menor, somamos a BASE a ele e marcamos
uma compensacao (+1) para ser adicionada ao dígito de baixo na próxima coluna.
Pseudocódigo:
FUNÇÃO Subtrair(Minuendo, Subtraendo, BASE):
compensacao = 0
resultado = ""
PARA cada posição i (da direita para a esquerda):
digito_baixo = Subtraendo[i] + compensacao
digito_cima = Minuendo[i]
SE digito_cima < digito_baixo:
# "Pega emprestado" da base (soma a base ao topo)
digito_cima = digito_cima + BASE
compensacao = 1
SENÃO:
compensacao = 0
diferenca = digito_cima - digito_baixo
ADICIONAR diferenca À ESQUERDA de resultado
RETORNAR resultadoImplementação em Python:
def subtrair_bases(n1: str, n2: str, base: int) -> str:
# Assumindo que n1 >= n2 para evitar números negativos
n1, n2 = n1[::-1].upper(), n2[::-1].upper()
tam_max = max(len(n1), len(n2))
n1 = n1.ljust(tam_max, '0')
n2 = n2.ljust(tam_max, '0')
compensacao = 0
resultado = []
for i in range(tam_max):
v_cima = DIGITOS.index(n1[i])
v_baixo = DIGITOS.index(n2[i]) + compensacao
if v_cima < v_baixo:
# Aplica a lógica do Carry Sub (soma a base em cima)
v_cima += base
compensacao = 1
else:
compensacao = 0
diferenca = v_cima - v_baixo
resultado.append(DIGITOS[diferenca])
# Remove zeros à esquerda resultantes (ex: 037 -> 37)
return "".join(resultado[::-1]).lstrip('0') or "0"
# --- Exemplos de Execução ---
# Base 10: 75 - 38
print(f"Base 10: {subtrair_bases('75', '38', 10)}")
# Resultado: 37
# Base 8: 52 - 17 (Exemplo do artigo: pegamos emprestado 8)
print(f"Base 8: {subtrair_bases('52', '17', 8)}")
# Resultado: 33 (Pois 2 virou 10 (2+8), 10-7=3. O 1 virou 2, 5-2=3)
# Base 16: 52 - 17
print(f"Base 16: {subtrair_bases('52', '17', 16)}")
# Resultado: 3B (Pois 2 virou 18 (2+16), 18-7=11(B). O 1 virou 2, 5-2=3)
# Base 2: 1101010 - 101101 (Exemplo adaptado)
print(f"Base 2: {subtrair_bases('1101010', '101101', 2)}")
# Resultado: 111101Conclusão e Próximos Passos #
Como vimos, a aritmética posicional é consistente: não importa se temos 2 símbolos (binário) ou 16 (hexadecimal), o algoritmo é o mesmo. A única coisa que muda é o valor que dispara o “vai-um” ou o “empréstimo”.
Dominar essas operações no papel é excelente para entender a lógica, mas levanta uma questão importante: será que o hardware do computador realiza subtrações pedindo emprestado bits vizinhos?
Na prática, construir circuitos que subtraem é caro e complexo. Por isso, a computação moderna usa um truque inteligente para transformar subtrações em somas, utilizando o conceito de Complemento de Dois e números com sinal. É exatamente sobre essa representação de números negativos que falaremos no próximo artigo.
Até lá!