Por que usar outras bases numéricas ao programar


35

Meus colegas de trabalho e eu estávamos tentando entender por que alguém faria o possível para programar números em uma base que não a base 10.

Sugeri que talvez você possa otimizar equações mais longas colocando as variáveis ​​na base correta com a qual está trabalhando (por exemplo, se você tiver apenas conjuntos de 5 de algo sem restos, poderá usar a base 5), mas não tenho certeza se isso é verdade.

Alguma ideia?


6
Você tem um exemplo específico que levantou essa questão? As coisas que estão na base 2 ou na base 16 obviamente têm seus benefícios, pois é mais fácil para o computador entender.
KDiTraglia 18/10/12

4
O que "números de programação na base ..." deveria significar? Existem números. Período. Eles são representados internamente em alguma base, mas isso principalmente não importa e não altera nenhuma regra aritmética.

12
@JMD - trabalhe com os moderadores para remover uma de suas duas postagens cruzadas e colocar uma aqui no P.SE. A postagem cruzada nos sites é mal vista. Os mods podem migrar perguntas para você.

10
@JMD - A postagem cruzada ainda não é algo que você deve fazer. Existe um processo de migração para essas perguntas, se necessário .
Oded

2
@JMD Não faça postagens cruzadas, uma pergunta adequada para mais de um site é extremamente rara. Desta vez, por exemplo, sua pergunta estava fora do tópico sobre estouro de pilha. Mas mesmo que sua pergunta seja adequada para ambos os sites, geralmente é difícil fazer compras em sites. Todos nós estamos oferecendo voluntariamente nosso tempo aqui, você poderia pelo menos esperar um pouco para avaliar as respostas que estava recebendo no Stack Overflow antes da postagem cruzada.
21133 yannis

Respostas:


59

O motivo usual para escrever números, em código, que não sejam a base 10, é porque você está mexendo em bits.

Para escolher um exemplo em C (porque se C é bom para qualquer coisa, é bom para manipulação de bits), digamos que algum formato de baixo nível codifique um número de 2 e 6 bits em um byte xx yyyyyy:

main() {
    unsigned char codevalue = 0x94; // 10 010100
    printf("x=%d, y=%d\n", (codevalue & 0xc0) >> 6, (codevalue & 0x3f));
}

produz

x=2, y=20

Em tal circunstância, escrever as constantes em hexadecimal é menos confuso do que escrevê-las em decimal, porque um dígito hexadecimal corresponde perfeitamente a quatro bits (meio byte; um 'nibble') e dois a um byte: o número 0x3ftem todos os bits definido na mordidela baixa e dois bits definidos na mordidela alta.

Você também pode escrever essa segunda linha em octal:

printf("x=%d, y=%d\n", (codevalue & 0300) >> 6, (codevalue & 077));

Aqui, cada dígito corresponde a um bloco de três bits. Algumas pessoas acham isso mais fácil de pensar, embora eu ache bastante raro atualmente.


Outro exemplo pode ser o uso do "número mágico" 0xDEADBEEF. Veja esta publicação stackoverflow.com/questions/5907614/0xdeadbeef-vs-null
Etsitpab Nioliv

45

A principal razão pela qual uso diferentes bases é quando me importo com os bits.

É muito mais fácil ler

int mask=0xFF;
byte bottom_byte = value & mask;

do que

int mask=255;
byte bottom_byte = value & mask;

Ou imagine algo mais complexo

int mask=0xFF00FF00;
int top_bytes_by_word = value & mask;

comparado com

int mask=4278255360; //can you say magic number!? 
int top_bytes_by_word = value & mask;

Aqui está muito claro qual é a intenção dos exemplos hexadecimais, porque hex é basicamente apenas uma forma mais compacta de binário ... Por outro lado, a base-10 (o que usamos) não é tão boa quanto binária.

0xFF = b11111111 = 255
0xFFFF = b1111111111111111 = 65536
0xF0F0 = b1111000011110000 = 61680

Existem também outras bases que você pode usar em alguns idiomas. Você encontrará muito pouco uso de bases que não sejam binárias, hexadecimais e decimais. Algumas pessoas estranhas ainda usam octal, mas essa é a mais esotérica que você verá em um programa são.


2
Octal não é raro, 0 é octal :) (vi que em algum lugar da rede Stack Exchange, não consigo encontrá-lo agora).
Gerrit 18/10/12

2
@Earlz: pessoas com muitos dedos. :-)
Bryan Oakley

3
26 x 2 + 10 = Todas as letras maiúsculas e minúsculas e todos os números. Não é tão incomum. Também vi a Base 36 usada, que é apenas a versão que não diferencia maiúsculas de minúsculas da mesma.
Darrel Hoffman

3
@vasile: Há 60 minutos em uma hora e 60 segundos em um minuto porque as pessoas estavam usando os sistemas base 60, e não o contrário. Espero que você não acredite que exista algo na natureza que diga que deve haver 60 minutos em uma hora!
Joren

11
sim, eles leram nas estrelas e usaram a base 60 devido à medição do tempo. com 360 dias (= 6x60) por ano, não é uma loucura medir o tempo na base 60.
ytg 19/10/12

8

Como você provavelmente sabe, os computadores são baseados em binário - essa é a base 2.

É fácil converter entre as bases 2 e 4, 8 e 16 (e múltiplos semelhantes de 2), e manter essa tradução no código-fonte pode facilitar muito o trabalho com números.

Para idiomas de baixo nível, como Assembly e C, isso pode ser traduzido diretamente para operações do processador (deslocamento de bits para divisão e multiplicação, por exemplo), o que significa que o uso dessas bases numéricas acaba com um código muito mais rápido.

Além disso, nem todas as operações são operações numéricas - existem mapas de bits nos quais você precisa mexer diretamente com os bits - usar uma base 2 ou um dos múltiplos para fazer isso facilita as operações.

Se você quiser saber mais, recomendo a leitura de Code, de Charles Petzold .


3
O compilador não dá a mínima. Embora seja realmente mais fácil converter entre as bases listadas, uma conversão simples (lenta) para a base 10 também não é difícil, e a maioria dos idiomas úteis para a construção do compilador (você não usa assembly para isso) tem isso conversão disponível em sua biblioteca padrão; portanto, é efetivamente gratuito para compiladores.

11
Usar hexadecimal em C não se traduz em programas mais rápidos. O compilador não se importa com qual base você usa.
Charles Salvia

5
Não importa em que base o programa esteja escrito, o compilador o converterá em binário no momento da compilação. As instruções de montagem são idênticas.
Karl Bielefeldt

2
Os computadores corporativos são, de fato, baseados em um bool de tri-enery: true, false e "file not found" #
Martin Beckett


4

Fora de programas altamente especializados, é muito raro usar bases diferentes de 10, 16 ou 2.

A base 16 (hexadecimal) é útil simplesmente porque o intervalo completo de um byte (0-255) pode ser representado em dois dígitos (0x00-0xFF), o que pode facilitar muito o trabalho com despejos hexadecimais brutos ou dados binários. O hexadecimal também é útil ao usar máscaras de bits com operadores bit a bit, porque os dois dígitos de uma correspondência de bytes ajudam na legibilidade.

Mais raramente, a base 2 (binária) também pode ser usada com operações bit a bit, mas muitas linguagens de programação não suportam literais da base 2 e, de qualquer forma, o hexadecimal é muito mais conciso e legível.

Às vezes, a Base-8 (octal) também é usada devido às permissões de arquivo UNIX. Fora isso, é muito raro usar bases diferentes de 10 fora de contextos matemáticos altamente especializados.


Octal é frequentemente usado para especificar valores de caracteres e, às vezes, para despejar dados binários.
Caleb

3

O motivo válido mais comum para usar outras bases tem a ver com a facilidade de conversão na base 2: é trivial converter um número de base 8 ou base 16 em binário sem usar uma calculadora, memorizando uma pequena tabela de oito ou dezesseis números:

 0000 0     0001 1     0010 2     0011 3
 0100 4     0101 5     0110 6     0111 7

 1000 8     1001 9     1010 A     1011 B
 1100 C     1101 D     1110 E     1111 F

Isso abre várias possibilidades:

  • Quando um número representa uma composição de números binários significativos, você pode determinar os componentes individuais sem um computador. Por exemplo, se um número de 24 bits representa uma cor em RGB, é trivial dizer que 0xFF00FFé magenta (vermelho + azul); a tarefa é muito mais difícil quando você recebe uma16711935
  • Quando um número representa uma máscara de bit, é mais prático anotá-lo como um número hexadecimal compacto, em vez de um número binário muito mais longo
  • Certas arquiteturas fizeram o possível para facilitar a leitura do código binário quando impressas como números octais. O PDP-11 era um desses sistemas: o bit mais significativo permitiria diferenciar as operações de 8 bits das de 16 bits; os dois últimos grupos octais permitem informar os dois registros envolvidos na operação e assim por diante. Eu conhecia várias pessoas que podiam ler o código binário PDP-11 na tela sem um desmontador, mas eles precisavam que o código da máquina fosse impresso no sistema octal.

2

O computador (ou mais precisamente o compilador) realmente não se importa com o número base que você usa no seu código-fonte. As linguagens de programação mais usadas suportam as bases 8 (octal), 10 (decimal) e 16 (hexadecimal) diretamente. Alguns também possuem suporte direto para números de base 2 (binários). Idiomas especializados também podem suportar outras bases de números. (Por "suporte direto", quero dizer que eles permitem a entrada de números nessa base sem recorrer a truques matemáticos como deslocamento de bits, multiplicação, divisão etc. no próprio código-fonte. Por exemplo, C suporta diretamente a base-16 com seus0xprefixo de número e o conjunto regular de dígitos hexadecimais de 0123456789ABCDEF. Agora, esses truques podem ser úteis para facilitar a compreensão do número no contexto, mas contanto que você possa expressar o mesmo número sem eles, fazê-lo - ou não - é apenas uma conveniência.)

No final, no entanto, isso é inconseqüente. Digamos que você tenha uma declaração como esta a seguir:

int n = 10;

A intenção é criar uma variável inteira e inicializá-la com o número decimal 10. O que o computador vê?

i  n  t     n     =     1  0  ;
69 6e 74 20 6e 20 3d 20 31 30 3b (ASCII, hex)

O compilador tokenizará isso e perceberá que você está declarando uma variável do tipo intcom o nome ne atribuirá a ele algum valor inicial. Mas qual é esse valor?

Para o computador, e ignorando os problemas de ordenação e alinhamento de bytes, a entrada para o valor inicial da variável é 0x31 0x30. Isso significa que o valor inicial é 0x3130 (12592 na base 10)? Claro que não. O analisador de idiomas deve continuar lendo o arquivo na codificação de caracteres usada, para que seja lido 1 0seguido por um terminador de instrução. Uma vez que nesta linguagem a base 10 é assumida, ela lê (ao contrário) como "0 ones, 1 dezenas, end". Ou seja, um valor de 10 decimal.

Se especificamos um valor em hexadecimal e nossa linguagem usa 0xpara especificar que o seguinte valor está em hexadecimal, obtemos o seguinte:

i  n  t     n     =     0  x  1  0  ;
69 6e 74 20 6e 20 3d 20 30 78 31 30 3b (ASCII, hex)

O compilador vê 0x(0x30 0x78) e reconhece isso como o prefixo da base 16; portanto, procura um número válido da base 16 depois dele. Até o final do extrato, ele lê 10. Isso se traduz em 0 "uns", 1 "dezesseis", o que equivale a 16 na base 10. Ou 00010000 na base 2. Ou, do contrário, você gostaria de representá-lo.

Em qualquer um dos casos, e ignorando as otimizações por uma questão de simplicidade, o compilador aloca armazenamento suficiente para manter o valor de uma intvariável de tipo e coloca lá o valor lido no código-fonte em algum tipo de variável de retenção temporária. Ele (provavelmente muito mais tarde) grava os valores binários resultantes no arquivo de código do objeto.

Como você vê, a maneira como você escreve valores numéricos no código fonte é completamente irrelevante. Ele pode ter um muito ligeiro efeito sobre tempos de compilação, mas eu imagino que (mais uma vez, ignorando essas otimizações, como cache de disco pelo sistema operacional) coisas como turbulência aleatória em torno das travessas de rotação do disco, tempos de acesso ao disco, colisões de barramento de dados , etc., têm um efeito muito maior.

Conclusão: não se preocupe. Escreva números em uma base compatível com sua linguagem de programação preferida e que faça sentido de como o número será usado e / ou lido. Você gastou muito mais tempo lendo esta resposta do que jamais se recuperará em tempos de compilação sendo esperto sobre qual base de números usar no código-fonte. ;)


1

por que alguém faria o possível para programar números em uma base diferente da base 10.

Aqui estão alguns motivos que ainda não apareceram ...

x00 - Algumas APIs de sistemas operacionais e dispositivos de hardware esperam que os argumentos sejam hexadecimais / binários. Quando você codifica para essas APIs, é mais fácil usar os números no mesmo formato esperado pela API, em vez de convertê-los entre diferentes bases. Por exemplo, para enviar um byte de fim de mensagem a um servidor ou para enviar uma mensagem para fechar uma conexão com um canal de comunicação.

x01 - Você pode querer que seu aplicativo represente caracteres não disponíveis em determinados teclados, como o símbolo de direitos autorais (\ u00a9).

x02 - Para que algumas constantes / literais persistam (visualmente) em diferentes configurações de cultura, especialmente quando o código-fonte / arquivos são movidos entre desenvolvedores com diferentes configurações locais.

x03 - Para tornar seu código confuso e complexo - O bom é que o C # não suporta constantes octais!


1

A questão principal é representar uma única palavra do tamanho do computador de maneira razoável. O 6502 era um processador de 8 bits. O 4004 era um processador de 4 bits.

Ao lidar com um número de 4 ou 8 bits, funciona bem. Um número de 4 bits é um único caractere hexadecimal. Um número de 8 bits (um byte) tem dois dígitos hexadecimais. Os sistemas com capacidade para palavras de tamanho 2 são o padrão mais comum atualmente - 16 bits, 32 bits, 64 bits. Todos esses fatores se dividem por 4 para representar como hexadecimal.

Octal (base 8) foi usado em sistemas em que o tamanho da palavra era 12, 24 ou 36. O PDP8, IBM Mainframe e ICL 1900 de dias de idade os usavam. Essas palavras foram mais facilmente representadas usando octetos em vez de um intervalo limitado de hexadecimal (sim, eles também se dividem em 4).

Aparentemente, houve também uma redução de custos com o uso da numeração da base 8. Representando 12 bits no BCD, o primeiro dígito pode ser apenas de 0 a 4, mas o segundo, o terceiro e o quarto podem ser de 0 a 9. Se isso foi feito como hexadecimal, um possui 3 caracteres hexadecimais, mas cada um possui 16 valores possíveis. Era mais barato produzir um tubo nixie que tinha apenas 0-7 do que um que tinha 0-9 (com lógica adicional para BCD) ou 0-F para hexadecimal.

Ainda se vê octal hoje com permissões de arquivo unix (755, 644), onde proprietário, grupo e mundo têm cada um 3 bits representando as permissões.


No mundo da matemática, ocasionalmente se fazem coisas estranhas com bases diferentes. Por exemplo, uma sequência de Goodstein fraca do projeto euler 396 ... ou algo mais simples com números palindrômicos . Existe a propriedade de um número na base N que um número múltiplo de N-1 terá seus dígitos somados a um múltiplo de N-1 . Além disso, se N-1 é um quadrado perfeito, essa propriedade também existe para sqrt ( N-1 ). Isso tem algumas aplicações em certos problemas matemáticos.


11
Octal foi porque o PDP tinha 9/18 bits bytes, um número octal representa 3bits isso, se você byte é divisível por 3 faz muito sentido
Martin Beckett

11
O Octal também foi usado em alguns sistemas de 16 bits (principalmente o PDP-11), porque 15 - o número de bits, exceto o bit de sinal - se divide muito bem em 3. Ele foi amplamente utilizado no sistema operacional UNIX original (por exemplo, "od" é a ferramenta padrão para despejar arquivos binários e seu formato padrão é octal de 16 bits em vez de hexadecimal de 8 bits), não apenas para permissões. Também pode ser relevante que o conjunto de instruções PDP-11 tenha dois campos de operando de 6 bits.
Random832

O Octal também foi usado porque poderia ser exibido na tecnologia às vezes. Tubos Nexi, alguém? Ou outros monitores 0-9? Demorou um pouco para os displays AF aparecerem.
Jeremy J Starcher

1

No setor financeiro, existe um esquema identificador que é efetivamente base 36 . Ele usa os números de 0 a 9 e as letras BZ para representar dígitos com valores de 0 a 35. Ele ignora as vogais para impedir que nomes desagradáveis ​​sejam gerados.

Não é perfeito, no entanto. Houve um tempo em que uma empresa infeliz tinha a identidade B000BZ.


1

Razão # 1: porque todos os números no nível do circuito estão representados na base 2 (a chave elétrica está ligada ou desligada). Razão # 2: porque em um nível superior aos circuitos reais, os bits são agrupados em bytes e os bytes podem ser facilmente representados como dois dígitos hexadecimais, quando seriam necessários 3 dígitos decimais (e alguma validação) para representar todos os valores possíveis do byte.

Portanto, se você estiver trabalhando nesses níveis (ou aproximando-os, em algum ambiente gerenciado), é mais fácil trabalhar em binário ou hexadecimal do que decimal. As situações nas quais você faria isso são variadas, mas geralmente nunca são situações em que você só precisa de aritmética básica.


1

Uma área em que os números da base 16 (hexadecimal) são usados ​​com muita frequência é na especificação de cores, especialmente ao usar HTML / CSS para a web. As cores que usamos nos monitores digitais são especificadas usando uma combinação de 3 valores de intensidade para 3 cores "base" (RGB - vermelho, verde, azul) que são combinadas para criar qualquer uma das 16 milhões de cores exibidas (usando cores de 24 bits) )

Por exemplo, a intensidade total do verde em hexadecimal seria 0x00ff00e 65280em decimal. Agora imagine tentar "manualmente" misturar na sua cabeça uma cor que tenha partes iguais de vermelho e azul, digamos com meia intensidade, para criar um belo roxo :) Em hexadecimal, isso seria escrito simplesmente como se fosse 0x800080o valor decimal 8388736. Ele fica ainda mais fácil quando se trabalha com tons de cinza -% cinza 50 é 0x808080(hex) e 8421504(decimal), 75% é 0xC0C0C0e 12632256, e assim por diante.

Usar hexadecimal é muito mais intuitivo e qualquer pessoa familiarizada com esse uso de cores poderá imediatamente "adivinhar" a cor apenas observando o valor hexadecimal. Também é muito menos propenso a erros se você precisar usar a mesma cor várias vezes (o que geralmente é o caso).

Confira qualquer página da web (e, em particular, o CSS) para ver uma quantidade absurda de uso hexadecimal: D

NOTA: No CSS, os valores hexadecimais são gravados usando um #prefixo, por exemplo: #00ff00para verde, e às vezes também é reduzido para apenas três dígitos, como #0f0para verde.


0

Para alguns algoritmos, a base 2 faz mais sentido do que qualquer outra coisa. Por exemplo, você prefere escrever uma função para atravessar uma árvore binária ou uma árvore com 10 árias?

Mas, mais frequentemente, a base 2 é usada porque é assim que os computadores quase universalmente representam seus números. Isso significa que:

  • muitas operações são mais eficientes na base 2:
    • potências de multiplicação, divisão e módulo de 2 são muito mais rápidas que a divisão geral
    • sinalizadores e valores pequenos podem ser armazenados, recuperados e manipulados com mais eficiência como dígitos binários de um número maior.
  • operações que lêem, gravam e manipulam arquivos de dados e fluxos de dados de rede devem lidar diretamente com o fato de serem representadas como números binários.

Além disso, sempre há o aplicativo raro que exige inerentemente uma base ímpar que pode ser nem 2 ou 10.


2
Claro que eu usaria uma árvore de 10 anos. Qual é esse 2personagem estranho que você está usando?
CodesInChaos

0

É honestamente a preferência, se por algum motivo você tiver polidactilia e tiver 11 dedos ou gostar de contar com os dedos dos pés, assim você gosta de trabalhar na base 20, é honestamente sua decisão. Mas saiba que, em um tópico de universalidade, a maioria de nós que tem que lidar com bits e bytes diariamente será realmente marcada se conseguirmos algo que esteja fazendo manipulação de bits na base 19.

RAZÕES DA BASE x

Base 10 - Modelo de todas as nossas coisas, porque temos 10 dígitos contados (os pés são estranhos e fedorentos, por isso não os usamos).

Base 2 - Os computadores usam isso para bits (ligado / desligado). Isso está relacionado aos níveis de tensão legíveis que são propagados por portas / transistores / capacitores.

Base 8 - Antiga, quando os computadores não eram super enormes (ou quando eram espaciais), isso era bom para uma coisa ou outra (não gosto nem um pouco)

Base 16 - Bom para mostrar mordidelas superiores e inferiores de um byte para manipulação de bits. Isso é super útil no mundo incorporado / fpga / hardware.

BASES NORMAIS EM COMPUTADORES

Para ir com preferência, eu poderia dizer exatamente como "on" está em uma cor em um valor hexadecimal RGB que é dado a mim, isso consequentemente pode ser representado em um único int no hardware e, em seguida, com algumas mudanças podem ser devolvidas a mim fácil de usar, 1 cor complexa = 1 ponto de dados, ideal para processamento de imagens grandes com memória limitada. Compare isso com uma representação da base 10, você pode adicioná-los todos e armazená-los em um número, mas qual número é qual, ou talvez R é o tempo 10000, G é 100 e B é seu próprio espaço, são muitas operações matemáticas , geralmente as multiplicações custam mais ciclos do que um turno. Portanto, seu próximo pedaço de dados já está na fila antes de terminar com o processamento do último pedaço, opa, isso acabou agora.

Às vezes, é melhor trabalhar nas bases 2, 8 ou 16. Na maioria das máquinas, multiplicar por 2 é apenas uma mudança de bit, essas são super rápidas, o mesmo com uma divisão por 2.

Explicar ainda mais a idéia de um pouco de brincadeira. Há um grande número de vezes ao trabalhar em um ambiente incorporado que eu precisava para acessar uma variedade de luzes, interruptores ou outros itens mapeados de registro.

Nesse caso, atribuir um caractere, um byte ou um int inteiro a cada comutador seria ineficiente e tolo, um comutador ou luz possui 2 posições - ativada e desativada - por que atribuiria algo que tenha até 256 posições ou 2 ^ 16 posições etc. Cada luz em uma matriz pode acomodar 1 bit 8 ou 16 ou 32 ou 64 ou 128 (largura do seu tipo de dados) em uma única palavra / registro. A eficiência do espaço é necessária e bastante bem-vinda.

Usando qualquer coisa que seja base 2 ^ n em programação para lidar com dados RGB, muitos dados de sinal - GPS, áudio, ascii, etc. - são muito mais simples em hexadecimal, binário e octal, pois é assim que são representados na máquina e é possível discernir mais facilmente o que está sendo apresentado e como manipulá-lo.

USANDO BASES ESTRANHAS

Não há eficiência, a menos que você a codifique. Você quer a base 11, precisa configurar um tipo de dados para ele e sobrecarregar os operadores para manipular sua representação para o usuário. Não vejo razão para que um sistema contendo 5 itens, e apenas múltiplos de 5 itens precisem ser convertidos para a matemática de cinco itens. Além disso, é melhor orar para que quem decidiu escrever seu código para a base 271 o tenha documentado bem ou você possa gastar mais tempo entendendo o que vale a pena criar na base 271, porque todos os itens são múltiplos de 271.



0

Estou surpreso que todas as outras respostas não tenham mencionado dois usos muito comuns na computação para bases alternativas:

  1. Codificação : a codificação Base64, por exemplo, é extremamente comum. A codificação simplesmente interpreta uma série de bytes como um número binário grande (base-2) e converte esse número em um número Base64 representado por dígitos ASCII.
  2. Compactação : geralmente é desejável representar um número binário, decimal ou hexadecimal em uma base maior, a fim de diminuir a representação. Por exemplo, todos os encurtadores de bit como bit.ly estão fazendo isso. Ou você pode fazer isso para reduzir um GUID para uso em um URL.

    - 821F6321-881B-4492-8F84-942186DF059B (base-16 guid) 
    becomes
    - RRIDHW463YD8YXX7MIDI (base-36)
    - 3UFmaWDjj9lifYyuT0 (base-62)
    
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.