Conversor Binário

Binary
10 1010
Octal
52
Decimal
42
Hexadecimal
2a

Complemento de dois

8-bit
0010 1010
16-bit
0000 0000 0010 1010
32-bit
0000 0000 0000 0000 0000 0000 0010 1010
64-bit
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1010

Nada do que você digita aqui é armazenado, registrado ou compartilhado.

Converta um número entre binário, octal, decimal e hexadecimal, ou converta texto para binário e de volta. Os valores continuam exatos em qualquer tamanho, inclusive muito acima de 64 bits.

Como usar

  1. Escolha a base em que está digitando e informe seu valor.
  2. Todas as outras bases aparecem de uma vez, com complemento de dois abaixo.
  3. Mude para o modo Texto para converter palavras em binário e de volta.

Por que a aritmética é exata

Todas as conversões aqui rodam em BigInt, que não tem limite de tamanho nem arredondamento. Parece uma nota de rodapé de implementação, mas é justamente o principal que separa esta ferramenta da maioria dos conversores da web.

Números em JavaScript são doubles IEEE 754, e representam inteiros com exatidão só até 9.007.199.254.740.991, que é 2^53 menos um. Um conversor escrito do jeito óbvio acerta abaixo disso e erra em silêncio acima. É o pior tipo de falha: nenhum erro, nenhum aviso, só uma resposta com o tamanho e o formato certos que por acaso não é a resposta certa.

Esse limite é baixo o bastante para ser atingido o tempo todo. Um valor completo de 64 bits está muito além dele. Também estão IDs de banco gerados por snowflake, timestamps em nanossegundos, dumps de registradores de hardware, hashes e qualquer coisa lida de um endereço de memória de 64 bits. Se você está convertendo um número grande o bastante para ser interessante, um conversor comum é exatamente onde ele deixa de ser confiável.

Complemento de dois

Abaixo das quatro bases, o valor aparece como seria armazenado num inteiro com sinal de 8, 16, 32 ou 64 bits. Isso não é o mesmo que escrever um sinal de menos na frente dos dígitos binários, e essa diferença é o que confunde as pessoas ao ler memória.

No complemento de dois, um número negativo é formado invertendo todos os bits do seu valor absoluto e somando um. Em oito bits, -1 é 11111111 e -128 é 10000000. Não há um bit de sinal separado para remover, não existe zero negativo, e a soma funciona sem tratar o sinal como caso especial, e é por isso que todo processador comum armazena inteiros assim.

Isso também explica a faixa assimétrica. Oito bits guardam de -128 a 127, e não de -128 a 128, porque o zero ocupa uma das posições do lado positivo. Uma largura em que o valor não cabe é informada como tal, em vez de truncar em silêncio, já que um resultado truncado parece perfeitamente válido e não é.

Lendo a saída

Valores longos são agrupados para leitura rápida: binário em bytes de oito, hexadecimal em pares, decimal em milhares. O agrupamento é só visual e é removido de tudo o que você copia.

A entrada é propositalmente tolerante no mesmo sentido. Os prefixos 0x, 0b e 0o são aceitos e ignorados, assim como sublinhados, espaços e vírgulas usados como separadores, então um literal colado direto do código-fonte ou de um dump hexadecimal funciona sem limpeza prévia.

Texto para binário

O modo texto codifica o texto em UTF-8 e depois escreve cada byte como oito bits. No sentido inverso, os bits são lidos de volta como bytes e decodificados como UTF-8.

A alternativa - pegar diretamente a code unit de cada caractere - é o que a maioria das ferramentas de texto para binário faz, e ela quebra em dois pontos. Qualquer coisa acima de U+00FF produz mais de oito bits e já não se alinha com bytes. Pior: caracteres fora do Plano Multilíngue Básico, o que inclui a maioria dos emoji, são armazenados em JavaScript como duas code units substitutas; tratadas separadamente, viram duas metades sem sentido que não decodificam em nada do outro lado. Passar por UTF-8 evita os dois problemas, e é por isso que um emoji faz a ida e volta aqui e em outros lugares muitas vezes não. Letras acentuadas, como ç e ã, também voltam intactas.

Um número, quatro formas de escrever

Pegue 2.025. Em binário é 11111101001, em octal 3751, em hexadecimal 7E9. Nada mudou na quantidade; só mudou a base usada para escrevê-la. Os dígitos de qualquer base são valores posicionais: 7E9 é 7x256 mais 14x16 mais 9, e 11111101001 é a soma das potências de dois cujos bits estão ligados.

O hexadecimal ganha seu lugar porque dezesseis é dois elevado a quatro, então um dígito hexadecimal equivale exatamente a quatro bits e o mapeamento é memorizável: F é 1111, 8 é 1000, A é 1010. É por isso que dumps de memória, valores de cor, hashes e endereços MAC são escritos em hexadecimal e não em decimal - dá para ler os bits direto dos dígitos, sem conta nenhuma.

O octal sobrevive basicamente num lugar, as permissões de arquivo no Unix, pelo mesmo motivo: três bits por dígito mapeiam perfeitamente em leitura, escrita e execução, então 755 é rwxr-xr-x e não há nada para consultar.

Operações bit a bit, e para que servem as máscaras

Uma vez que o valor está em binário, os operadores bit a bit ficam óbvios. O AND mantém apenas os bits ligados nos dois operandos, que é como se testa uma flag: value AND 0b0100 é diferente de zero exatamente quando o terceiro bit está ligado. O OR liga bits, o XOR os inverte, o NOT inverte tudo, e deslocar à esquerda ou à direita multiplica ou divide por potências de dois.

É por isso que flags são guardadas como bits isolados e não como booleanos separados. Um campo de permissões, um conjunto de chaves de funcionalidade ou as opções de um pacote de rede cabem num inteiro, e verificar uma delas é uma única instrução. A constante com a qual se faz o AND chama-se máscara, e escrevê-la em binário ou hexadecimal deixa seu propósito visível de um jeito que o equivalente decimal nunca deixa.

Os deslocamentos têm uma armadilha que vale conhecer: na maioria das linguagens, um deslocamento à direita num valor com sinal preserva o bit de sinal, então -8 deslocado à direita é -4, e não um número positivo enorme. Linguagens que oferecem as duas formas escrevem a outra de modo diferente, como o operador >>> do JavaScript.

Como um número fica na memória

Um valor escrito como 7E9 não diz como ele está armazenado. A largura importa: o mesmo número ocupa um, dois, quatro ou oito bytes conforme o tipo, e um valor grande demais para a largura é truncado ou dá a volta, em vez de crescer.

A ordem dos bytes também importa. Máquinas little-endian, que é praticamente tudo o que você vai encontrar, guardam o byte menos significativo primeiro, então o valor de 32 bits 0x000007E9 aparece num dump como E9 07 00 00. A ordem big-endian é o inverso e é o que os protocolos de rede especificam, por isso se chama ordem de bytes de rede e por isso existem funções de conversão em toda fronteira de socket. Ler um dump sem saber qual das duas você está vendo produz um absurdo dito com convicção.

Tipos com e sem sinal da mesma largura guardam os mesmos bits e os interpretam de formas diferentes: 0xFF é 255 como byte sem sinal e -1 como byte com sinal. Nada nos bytes diz qual está correto; apenas o tipo diz.

Ponto flutuante é outro sistema

Tudo acima trata de inteiros. Um double é armazenado como um bit de sinal, um expoente de 11 bits e uma fração de 52 bits, o que significa que ele representa um número como uma fração multiplicada por uma potência de dois. Valores que não são exatamente representáveis assim são arredondados para o mais próximo que é.

Essa é a explicação inteira do resultado famoso em que 0,1 mais 0,2 não dá 0,3. Um décimo em binário é uma fração periódica, exatamente como um terço em decimal, então é guardado ligeiramente fora, e dois valores ligeiramente fora somam algo ligeiramente fora. A aritmética está correta; o que está errado é a expectativa de que frações decimais sobrevivam ao armazenamento binário.

As regras práticas seguem daí: nunca guarde dinheiro num float, use centavos inteiros ou um tipo decimal; compare floats com uma tolerância, não com igualdade; e saiba que inteiros acima de 2^53 perdem precisão num double, que é por que este conversor usa aritmética de precisão arbitrária.

Onde você encontra essas bases na prática

Hexadecimal aparece sempre que bytes são mostrados a uma pessoa. Uma cor em CSS são três bytes em hexadecimal; um endereço MAC são seis; um digest SHA-256 são trinta e dois, escritos como sessenta e quatro caracteres. Endereços de memória, códigos de erro de sistemas operacionais e registradores de hardware também são hexadecimais porque as fronteiras de bits coincidem com os dígitos.

Binário aparece onde bits individuais carregam significado: máscaras de rede, registradores de hardware, bits de permissão, flags de funcionalidade e as tabelas de codificação de formatos como QR Code e UTF-8. Ler UTF-8 é um bom exemplo de por que a base importa: um byte que começa com 0 é ASCII, um que começa com 110 inicia uma sequência de dois bytes, e um que começa com 10 é um byte de continuação. Essa estrutura é invisível em decimal e evidente em binário.

O octal recuou em grande parte para as permissões de arquivo e alguns formatos antigos, mas mantém uma armadilha que vale lembrar: em C, no JavaScript anterior ao ES5 e em vários formatos de configuração, um número escrito com zero à esquerda é octal, então 0755 não é setecentos e cinquenta e cinco. O JavaScript moderno usa o prefixo explícito 0o, e o YAML 1.2 abandonou a regra do zero à esquerda por completo, o que é sua própria fonte de surpresa quando um modo de arquivo é lido como número decimal.

Perguntas frequentes

Isso continua exato com números muito grandes?
Sim. Toda a aritmética usa BigInt, que é exato em qualquer tamanho. Conversores construídos sobre números JavaScript comuns perdem precisão acima de 2^53, cerca de 9 quatrilhões, e passam a devolver respostas que parecem plausíveis mas estão erradas. Um valor completo de 64 bits já ultrapassa esse limite, então isso importa mais vezes do que parece.
O que é complemento de dois e por que mostrá-lo?
É como inteiros com sinal são de fato armazenados na memória. Em complemento de dois de 8 bits, -1 é 11111111 e não um bit de sinal mais 1. Ver a forma armazenada é o que você precisa ao ler um dump de registrador ou depurar um protocolo. Larguras em que o valor não cabe dizem isso em vez de truncar em silêncio.
Posso colar valores com prefixos 0x ou 0b?
Sim. Esses prefixos são aceitos e ignorados, assim como sublinhados, espaços e vírgulas usados para agrupar, então você pode colar direto do código-fonte.
Como o texto é convertido em binário?
O texto é primeiro codificado em UTF-8, depois cada byte é escrito como oito bits. Isso significa que japonês, chinês, coreano e emoji voltam intactos. Ferramentas que leem códigos de caractere diretamente produzem lixo para qualquer coisa fora do ASCII, e um único emoji vira duas metades quebradas.

Última atualização:

Relatar um problema

Inclua os passos, o resultado esperado e o resultado real. Remova segredos e dados pessoais.

Ferramentas relacionadas