Representando números: bases negativas


Artigo anterior aqui, sobre diferentes formas de representar números.

Continuando a explorar diferentes métodos para representar números, vamos tratar de bases negativas. Nesse artigo, em especial, vamos analisar a base 10-10, também chamada de negadecimal.

Como primeiro exemplo, vamos converter o número 784(10)784_{(10)} na base negadecimal (lembrando que o número entre parênteses após o número representa qual a base de representação). A decomposição pode ser feita como abaixo:

784(10)=7×(10)2+8×(10)1+4×(10)0=7×1008×10+4=70080+4=624(10)784_{(10)} = 7 \times (-10)^2 + 8 \times (-10)^1 + 4 \times (-10)^0 = 7 \times 100 - 8 \times 10 + 4 = 700 - 80 + 4 = 624_{(-10)}

Nesse cenário, ao invés das potências de 10 que usamos na base decimal para compor o número, temos potências de 10 com sinais alternados. Nessa linha, para representar o número 17-17 em base negadecimal precisamos encontrar os dígitos entre 0 e 9 que, multiplicados pelas potências 1, 10-10, 100, 1000-1000, etc. somam 17-17. Notando que podemos escrever 17=20+3-17 = -20 + 3 temos:

17(10)=20+3=2(10)1+3(10)0=32(10)-17_{(10)} = -20 + 3 = 2(-10)^1 + 3(10)^0 = 32_{(-10)}

Isso mostra que em base negadecimal temos números negativos representados sem necessidade de um sinal negativo. Na verdade, temos mais que isso: na base negadecimal podemos representar qualquer número negativo sem a necessidade do sinal negativo.

Isso pode ser derivado diretamente do algoritmo da divisão: para um número nn inteiro fazemos

n=(10)q+rn = (-10)q + r

Onde:

  1. qq é o quociente da divisão;
  2. rr é o resto da divisão, 0r<100 \leq |r| < 10.

Como q<n|q| < n para n>10n > |10|, o algoritmo termina.

Aplicando o primeiro passo do algoritmo para o número n=17n = -17 temos:

17=1×(10)7-17 = 1 \times (-10) - 7

Aqui temos q=1q = 1 e r=7r = -7. Como o resto é negativo, precisamos aplicar dois ajustes: somamos 1 no quociente e somamos o valor absoluto da base no resto:

  • q:=q+1q := q + 1
  • r:=r+br := r + |b|

Então temos, no exemplo, q=2q = 2 e r=7+10=3r = -7 + 10 = 3, assim:

17=2×(10)+3-17 = 2 \times (-10) + 3

E podemos continuar o algoritmo:

2=(10)×0+22 = (-10) \times 0 + 2

E aí compomos o número normalmente, concatenando os restos na ordem inversa: 23(10)23_{(-10)}. Podemos usar a classe MetaNumber para avaliar a conversão do número. O parâmetro verbose=True na função to_base mostra os passos do algoritmo da divisão — note o ajuste no quociente e base.

Classe MetaNumber (Python), conversão de -17(10) para 23(-10)

O algoritmo dá uma volta maior no último passo, mas o resultado é o mesmo.

Comparação com a base decimal

Podemos usar a classe MetaNumber para gerar uma sequência de números e convertê-los para base negadecimal:

import os

# Diretório com o script MetaNumber.py
diretorio = r'C:\Scripts'
os.chdir(diretorio)

from MetaNumber import MetaNumber

# Listas com os resultados
decimal = []
negadecimal = []

# Varre os números e converte
for i in range(-10, 11):
    num = MetaNumber(i, base=10)
    decimal.append(i)
    negadecimal.append(num.to_base(-10).force_base10())

Inteiros -10 a 10 e suas representações na base negadecimal

Sabemos agora que: (1) a representação de um número em base negadecimal não precisa do sinal negativo, e (2) a base negadecimal usa os mesmos dez dígitos da base decimal. Podemos então pensar na base negadecimal como uma aplicação que leva o conjunto dos números inteiros nos números inteiros positivos.

Assim conseguimos plotar gráficos comparando a representação decimal e negadecimal para conseguirmos “ver” a conversão entre bases. Analisando o intervalo de 900-900 a 900900, podemos notar que:

  1. O intervalo de 900(10)-900_{(10)} a 900(10)900_{(10)} é mapeado no intervalo 0(10)0_{(-10)} a 1999(10)1999_{(-10)}, mas não de forma sobrejetora: entre 900-900 e 900900 temos 1800 valores versus 1999 na imagem.
  2. O mapeamento não é contínuo — mais que isso, não apresenta nenhum ponto de continuidade — nem mesmo considerando números reais.

Mesmo considerando números entre -1 e 1 o mapeamento não mantém continuidades