Um formato de número de computador é a representação interna de valores numéricos no hardware e software de dispositivos digitales, tais como computadores programáveis e calculadoras. Os valores numéricos são armazenados como agrupamentos de bits, tais como bytes e palavras. A codificação entre valores numéricos e padrões de bits é escolhida para a conveniência da operação do computador; a codificação usada pelo conjunto de instruções do computador geralmente requer conversão para uso externo, como para impressão e exibição. Diferentes tipos de processadores podem ter diferentes representações internas de valores numéricos, e convenções distintas são usadas para números inteiros e reais. A maioria dos cálculos é realizada com formatos de números que cabem em um registrador do processador, mas some sistemas de software permitem a representação de números arbitrariamente grandes usando múltiplas palavras de memória.

Representação de números binários

Os computadores representam dados em conjuntos de dígitos binários. A representation é composta por bits que, por sua vez, são agrupados em conjuntos maiores, como os bytes.

Um bit é um dígito binário que representa um de dois estados. O conceito de um bit pode ser entendido como um valor que é 1 ou 0, ligado ou desligado, sim ou não, verdadeiro ou falso, ou codificado por uma chave ou comutador de algum tipo. Embora um único bit, por si só, seja capaz de representar apenas dois valores, uma cadeia de bits pode ser usada para representar valores maiores. Por exemplo, uma cadeia de três bits pode representar até oito valores distintos, conforme ilustrado na Tabela 1. À medida que o número de bits que compõem uma cadeia aumenta, o número de combinações possíveis de 0 e 1 aumenta exponencialmente. Um único bit permite apenas duas combinações de valores, dois bits combinados podem formar quatro valores separados, três bits formam oito e assim por diante, crescendo com a fórmula

2

n

{\displaystyle 2^{n}}

. A quantidade de combinações possíveis dobra com cada dígito binário adicionado, conforme ilustrado na Tabela 2. Agrupamentos com um número específico de bits são usados para representar coisas variadas e possuem nomes específicos. Um byte é uma cadeia de bits que contém o número de bits necessários para representar um caractere. Na maioria dos computadores modernos, trata-se de uma cadeia de oito bits. Como a definição de um byte está relacionada ao número de bits que compõem um caractere, alguns computadores mais antigos usavam um comprimento de bit diferente para o seu byte. Em muitas arquiteturas de computadores, o byte é a menor unidade endereçável. Por exemplo, mesmo que processadores de 64 bits possam endereçar a memória a sessenta e quatro bits por vez, eles ainda podem dividir essa memória em pedaços de oito bits. Isso é chamado de memória endereçável por byte. Historicamente, muitas CPUs liam dados em algum múltiplo de oito bits. Como o tamanho de byte de oito bits é muito comum, mas a definição não é padronizada, o termo octeto é algumas vezes usado para descrever explicitamente uma sequência de oito bits. Um nibble (às vezes nybble) é um número composto por quatro bits. Sendo um meio-byte, o nibble recebeu esse nome como um jogo de palavras. Uma pessoa pode precisar de várias mordiscadas para dar uma mordida em algo; da mesma forma, um nybble é uma parte de um byte. Como quatro bits permitem dezesseis valores, um nibble também é conhecido às vezes como um dígito hexadecimal.

Exibição de números octais e hexadecimais

A codificação octal e hexadecimal são maneiras convenientes de representar números binários, conforme usado por computadores. Engenheiros de computação frequentemente precisam escrever quantidades binárias, mas na prática escrever um número binário como 1001001101010001 é tedioso e propenso a erros. Portanto, as quantidades binárias são escritas em um formato de número de base 8 ("octal") ou, muito mais comumente, de base 16 ("hexadecimal" ou hex). No sistema decimal, existem 10 dígitos, de 0 a 9, que se combinam para formar números. No sistema octal, existem apenas 8 dígitos, de 0 a 7. Ou seja, o valor de um "10" octal é o mesmo que um "8" decimal, um "20" octal é um "16" decimal e assim por diante. No sistema hexadecimal, existem 16 dígitos, de 0 a 9 seguidos, por convenção, de A a F. Ou seja, um "10" hexadecimal é o mesmo que um "16" decimal e um "20" hexadecimal é o mesmo que um "32" decimal. Um exemplo e comparação de números em diferentes bases é descrito na tabela abaixo. Ao digitar números, caracteres de formatação são usados para descrever o sistema numérico, por exemplo, 000_0000B ou 0b000_00000 para binário e 0F8H ou 0xf8 para números hexadecimais.

Convertendo entre bases

Cada um desses sistemas numéricos é um sistema posicional, mas enquanto os pesos decimais são potências de 10, os pesos octais são potências de 8 e os pesos hexadecimais são potências de 16. Para converter de hexadecimal ou octal para decimal, multiplica-se o valor de cada dígito pelo valor de sua posição e depois soma-se os resultados. Por exemplo:

octal

756

=

( 7 ×

8

2

) + ( 5 ×

8

1

) + ( 6 ×

8

0

)

=

( 7 × 64 ) + ( 5 × 8 ) + ( 6 × 1 )

=

448 + 40 + 6

=

decimal

494

hex

3 b 2

=

( 3 ×

16

2

) + ( 11 ×

16

1

) + ( 2 ×

16

0

)

=

( 3 × 256 ) + ( 11 × 16 ) + ( 2 × 1 )

=

768 + 176 + 2

=

decimal

946

{\displaystyle {\begin{aligned}&{\text{octal }}756\\[5pt]={}&(7\times 8^{2})+(5\times 8^{1})+(6\times 8^{0})\\[5pt]={}&(7\times 64)+(5\times 8)+(6\times 1)\\[5pt]={}&448+40+6\\[5pt]={}&{\text{decimal }}494\end{aligned}}\qquad {\begin{aligned}&{\text{hex }}\mathrm {3b2} \\[5pt]={}&(3\times 16^{2})+(11\times 16^{1})+(2\times 16^{0})\\[5pt]={}&(3\times 256)+(11\times 16)+(2\times 1)\\[5pt]={}&768+176+2\\[5pt]={}&{\text{decimal }}946\end{aligned}}}

Representando frações em binário

Números em ponto fixo A formatação em ponto fixo pode ser útil para representar frações em binário. O número de bits necessários para a precisão e o intervalo desejados deve ser escolhido para armazenar as partes inteira e fracionária de um número. Por exemplo, usando um formato de 32 bits, 16 bits podem ser usados para a parte inteira e 16 para a fracionária. O bit do oito é seguido pelo bit do quatro, depois pelo bit do dois e pelo bit do um. Os bits fracionários continuam o padrão estabelecido pelos bits inteiros. O próximo bit é o bit do meio, depois o bit do quarto, o bit do oitavo e assim por diante. Por exemplo:

Esta forma de codificação não pode representar alguns valores em binário. Por exemplo, para a fração ⁠1/5⁠, que é 0.2 em decimal, as aproximações mais próximas seriam as seguintes:

Mesmo que mais dígitos sejam usados, uma representação exata é impossível. O número ⁠1/3⁠, escrito em decimal como 0.333333333..., continua indefinidamente. Se for terminado prematuramente, o valor não representará ⁠1/3⁠ com precisão.

Números em ponto flutuante Embora tanto inteiros sinalizados quanto não sinalizados sejam usados em sistemas digitais, mesmo um inteiro de 32 bits não é suficiente para lidar com todo o intervalo de números que uma calculadora pode processar, sem contar as frações. Para aproximar o maior intervalo e precisão dos números reais, temos que abandonar os inteiros sinalizados e os números em ponto fixo e mudar para um formato de "ponto flutuante". No sistema decimal, estamos familiarizados com números em ponto flutuante da forma de Notação científica:

1.1030402 ×

10

5

= 1.1030402 × 100000 = 110304.02

{\displaystyle 1.1030402\times 10^{5}=1.1030402\times 100000=110304.02}

ou, de forma mais compacta:

1.1030402E5 que significa "1.1030402 vezes 1 seguido de 5 zeros". Temos um certo valor numérico (1.1030402) conhecido como "significando", multiplicado por uma potência de 10 (E5, significando

10

5

{\displaystyle 10^{5}}

ou 100.000), conhecido como um "expoente". Se tivermos um expoente negativo, isso significa que o número é multiplicado por um 1 que está tantas posições à direita do ponto decimal. Por exemplo:

2.3434

E

− 6 = 2.3434 ×

10

− 6

= 2.3434 × 0.000001 = 0.0000023434

{\displaystyle 2.3434{\text{E}}-6=2.3434\times 10^{-6}=2.3434\times 0.000001=0.0000023434}

A vantagem deste esquema é que, ao usar o expoente, podemos obter um intervalo muito mais amplo de números, mesmo que o número de dígitos no significando, ou a "precisão numérica", seja muito menor do que o intervalo. Formatos semelhantes de ponto flutuante binário podem ser definidos para computadores. Existe uma série de esquemas desse tipo, sendo o mais popular definido pelo Instituto de Engenheiros Eletricistas e Eletrônicos (IEEE). A especificação do padrão IEEE 754-2008 define um formato de ponto flutuante de 64 bits com:

um expoente binário de 11 bits, usando o formato "excesso-1023". Excesso-1023 significa que o expoente aparece como um inteiro binário não sinalizado de 0 a 2047; subtrair 1023 fornece o valor real sinalizado um significando de 52 bits, também um número binário não sinalizado, definindo um valor fracionário com um "1" implícito condutor um bit de sinal, fornecendo o sinal do número. Com os bits armazenados in 8 bytes de memória:

onde "S" denota o bit de sinal, "x" denota um bit de expoente e "m" denota um bit de significando. Uma vez que os bits foram extraídos, eles são convertidos com o cálculo:

sinal

× ( 1 +

significando fracionário

) ×

2

expoente

− 1023

{\displaystyle {\text{sinal}}\times (1+{\text{significando fracionário}})\times 2^{{\text{expoente}}-1023}}

Este esquema fornece números válidos até cerca de 15 dígitos decimais, com o seguinte intervalo de números:

A especificação também define vários valores especiais que não são números definidos, conhecidos como NaNs, de "Not A Number" (Não é um Número). Eles são usados por programas para designar operações inválidas e afins. Alguns programas também usam números de ponto flutuante de 32 bits. O esquema mais comum usa um significando de 23 bits com um bit de sinal, mais um expoente de 8 bits no formato "excesso-127", fornecendo sete dígitos decimais válidos.

Os bits são convertidos para um valor numérico com o cálculo:

sinal

× ( 1 +

significando fracionário

) ×

2

expoente

− 127

{\displaystyle {\text{sinal}}\times (1+{\text{significando fracionário}})\times 2^{{\text{expoente}}-127}}

levando ao seguinte intervalo de números:

Tais números em ponto flutuante são conhecidos como "reais" ou "floats" em geral, mas com uma série de variações: Um valor float de 32 bits é às vezes chamado de "real32" ou "precisão simples" (single). Um float de 64 bits é às vezes chamado de "real64" ou "precisão dupla" (double). A relação entre números e padrões de bits é escolhida para conveniência na manipulação do computador; oito bytes armazenados na memória do computador podem representar um real de 64 bits, dois reais de 32 bits, quatro inteiros com ou sem sinal, ou algum outro tipo de dado que caiba em oito bytes. A única diferença é como o computador os interpreta. Se o computador armazenasse quatro inteiros não sinalizados e depois os lesse de volta da memória como um real de 64 bits, quase sempre seria um número real perfeitamente válido, embora fossem dados inúteis. Apenas um intervalo finito de números reais pode ser representado com um determinado número de bits. Operações aritméticas podem causar transbordo positivo (overflow) ou transbordo negativo (underflow), produzindo um valor grande ou pequeno demais para ser representado. A representação possui uma precisão limitada. Por exemplo, apenas 15 dígitos decimais podem ser representados com um real de 64 bits. Se um número em ponto flutuante muito pequeno for adicionado a um muito grande, o resultado será apenas o grande. O número pequeno era pequeno demais para sequer aparecer em 15 ou 16 dígitos de resolução, e o computador efetivamente o descarta. Analisar o efeito da precisão limitada é um problema bem estudado. Estimativas da magnitude dos erros de arredondamento e métodos para limitar seu efeito em grandes cálculos fazem parte de qualquer projeto de grande computação. O limite de precisão é diferente do limite de intervalo, pois afeta o significando, não o expoente. O significando é uma fração binária que não corresponde necessariamente de forma perfeita a uma fração decimal. Em muitos casos, uma soma de potências recíprocas de 2 não corresponde a uma fração decimal específica, e os resultados das computações serão ligeiramente imprecisos. Por exemplo, a fração decimal "0.1" é equivalente a uma fração binária infinitamente periódica: 0.000110011 ...

Números em linguagens de programação Programar em linguagem de montagem (assembly) requer que o programador acompanhe a representação dos números. Onde o processador não suporta uma operação matemática necessária, o programador deve desenvolver um algoritmo e uma sequência de instruções adequados para realizar a operação; em alguns microprocessadores, até mesmo a multiplicação de inteiros deve ser feita por software. Linguagens de programação de alto nível, como Ruby e Python, oferecem um número abstrato que pode ser um tipo expandido, como racional, bignum ou complexo. As operações matemáticas são realizadas por rotinas de biblioteca fornecidas pela implementação da linguagem. Um determinado símbolo matemático no código-fonte, por meio de sobrecarga de operadores, invocará um código de objeto diferente e apropriado para a representação do tipo numérico; operações matemáticas em qualquer número — seja sinalizado, não sinalizado, racional, ponto flutuante, ponto fixo, integral ou complexo — são escritas exatamente da mesma maneira. Algumas linguagens, como REXX e Java, fornecem operações de ponto flutuante decimal, que geram erros de arredondamento de uma forma diferente.

Veja também Aritmética de precisão arbitrária Número binário Código de Gray Sistema de numeração

Referências