Share via


Representação de ponto flutuante IEEE

O MICROSOFT C++ (MSVC) é consistente com os padrões numéricos do IEEE. O padrão IEEE-754 descreve formatos de ponto flutuante, uma maneira de representar números reais no hardware. Há pelo menos cinco formatos internos para números de ponto flutuante que são representáveis no hardware direcionado pelo compilador MSVC. O compilador usa apenas dois deles. Os formatos de precisão simples (4 bytes) e de precisão dupla (8 bytes) são usados no MSVC. A precisão simples é declarada usando a palavra-chave float. A precisão dupla é declarada usando a palavra-chave double. O padrão IEEE também especifica formatos de meia precisão (2 bytes) e precisão quádrupla (16 bytes) e um formato de precisão estendida dupla (10 bytes), que alguns compiladores C e C++ implementam como o tipo de dados long double. No compilador MSVC, o tipo de dados long double é tratado como um tipo distinto, mas o tipo de armazenamento é mapeado para double. No entanto, há suporte intrínseco e de linguagem de assembly para cálculos usando os outros formatos, incluindo o formato de precisão estendida dupla, em que há suporte para hardware.

Os valores são armazenados da seguinte maneira:

Valor Armazenado como
precisão simples bit de sinal, expoente de 8 bits, significando de 23 bits
double-precision bit de sinal, expoente de 11 bits, significando de 52 bits

Em formatos de precisão simples e precisão dupla, é assumido um 1 inicial, na parte fracionária. A parte fracionária é chamada de significando (às vezes conhecida como mantissa). Esse 1 à esquerda não é armazenado na memória, portanto, os significandos têm, na verdade, 24 ou 53 bits, mesmo que seja armazenado um bit a menos. O formato de precisão estendida dupla realmente armazena esse bit.

Os expoentes são polarizados pela metade de seu valor possível. Isso significa que você subtrai esse desvio do expoente armazenado para obter o expoente real. Se o expoente armazenado for menor que o desvio, na verdade será um expoente negativo.

Os expoentes são polarizados da seguinte maneira:

Expoente Polarizado por
8 bits (precisão simples) 127
11 bits (precisão dupla) 1023

Esses expoentes não são potência de dez; eles são potência de dois. Ou seja, expoentes armazenados de 8 bits podem variar de -127 a 127, armazenados como 0 a 254. O valor 2127 é aproximadamente equivalente a 1038, que é o limite real de precisão simples.

O significando é armazenado como uma fração binária do formulário 1.XXX... . Essa fração tem um valor maior ou igual a 1 e menor que 2. Números reais são sempre armazenados na forma normalizada. Ou seja, o significando é deslocado para a esquerda de modo que o bit de alta ordem do significando será sempre 1. Como esse bit é sempre 1, ele é assumido (não armazenado) nos formatos de precisão simples e precisão dupla. O ponto binário (não decimal) é considerado apenas à direita do 1 à direita.

O formato para representação de ponto flutuante é o seguinte:

Formatar byte 1 byte 2 byte 3 byte 4 ... byte n
precisão simples SXXXXXXX XMMMMMMM MMMMMMMM MMMMMMMM
double-precision SXXXXXXX XXXXMMMM MMMMMMMM MMMMMMMM ... MMMMMMMM

S representa o bit de sinal, os X's são os bits expoentes polarizados e os M's são os bits de significando. O bit mais à esquerda é assumido em formatos de precisão simples e precisão dupla.

Para deslocar o ponto binário corretamente, primeiro você despolariza o expoente e, em seguida, move o ponto binário para a direita ou para a esquerda, pelo número apropriado de bits.

Valores especiais

Os formatos de ponto flutuante incluem alguns valores tratados de maneira especial.

Zero

Zero não pode ser normalizado, o que o torna não representável na forma normalizada de um valor de precisão simples ou precisão dupla. Um padrão de bit especial de todos os zeros representa 0. Também é possível representar -0 como zero com o conjunto de bits de sinal, mas a comparação de -0 e 0 sempre será igual.

Infinidades

Os valores +∞ e −∞ são representados por um expoente de todos os uns e um significando que são todos zeros. Positivo e negativo são representados usando o bit de sinal.

Subnormais

É possível representar números de magnitude menor do que o menor número em forma normalizada. Eles são chamados de números subnormais ou denormais. Se o expoente for todos zeros e o significando não for zero, o bit principal implícito do significando será considerado zero, não um. A precisão dos números subnormal diminui à medida que o número de zeros à esquerda no significando aumenta.

NaN – não é um número

É possível representar valores que não são números reais, como 0/0, no formato de ponto flutuante IEEE. Um valor desse tipo é chamado de NaN. Um NaN é representado por um expoente de todos um e um significando diferente de zero. Há dois tipos de NaNs, NaNs silenciosos ou QNaNs e NaNs de sinalização ou SNaNs. Os NaNs silenciosos têm um líder no significando e são propagados por meio de uma expressão. Eles representam um valor indeterminado, como o resultado da divisão por infinito ou multiplicação de um infinito por zero. Os NaNs de sinalização têm um zero à esquerda no significando. Eles são usados para operações que não são válidas, para sinalizar uma exceção de hardware de ponto flutuante.

Exemplos

Veja a seguir alguns exemplos no formato de precisão simples:

  • Para o valor 2, o bit de sinal é zero. O expoente armazenado é 128 ou 1000 0000 em binário, que é 127 mais 1. O significando binário armazenado é (1.) 000 0000 0000 0000 0000 0000 0000, que tem 1 à esquerda e ponto binário implícitos, portanto, o significando real é um.

    Valor Fórmula Representação binária Hexadecimal
    2 1 * 21 0100 0000 0000 0000 0000 0000 0000 0000 0x40000000
  • O valor -2. O mesmo que +2, exceto que o bit de sinal está definido. O mesmo é verdadeiro para o negativo de todos os números de ponto flutuante de formato IEEE.

    Valor Fórmula Representação binária Hexadecimal
    -2 -1 * 21 1100 0000 0000 0000 0000 0000 0000 0000 0xC0000000
  • O valor 4. Mesmo significando, o expoente aumenta em um (o valor polarizado é 129 ou 100 0000 1 em binário.

    Valor Fórmula Representação binária Hexadecimal
    4 1 * 22 0100 0000 1000 0000 0000 0000 0000 0000 0x40800000
  • O valor 6. Mesmo expoente, significando é metade maior. É (1.) 100 0000... 0000 0000, que, como é uma fração binária, é 1 1/2 porque os valores dos dígitos fracionários são 1/2, 1/4, 1/8 e assim por diante.

    Valor Fórmula Representação binária Hexadecimal
    6 1,5 * 22 0100 0000 1100 0000 0000 0000 0000 0000 0x40C00000
  • O valor 1. Mesmo significando que outras potências de dois, o expoente polarizado é um menor que dois em 127, ou 011 1111 1 em binário.

    Valor Fórmula Representação binária Hexadecimal
    1 1 * 20 0011 1111 1000 0000 0000 0000 0000 0000 0x3F800000
  • O valor 0,75. O expoente polarizado é 126, 011 1111 0 em binário e o significando é (1,) 100 0000... 0000 0000, que é 1 1/2.

    Valor Fórmula Representação binária Hexadecimal
    0,75 1,5 * 2-1 0011 1111 0100 0000 0000 0000 0000 0000 0x3F400000
  • O valor 2.5. Exatamente igual a dois, exceto que o bit que representa 1/4 está definido no significando.

    Valor Fórmula Representação binária Hexadecimal
    2.5 1,25 * 21 0100 0000 0010 0000 0000 0000 0000 0000 0x40200000
  • 1/10 é uma fração repetida no binário. O significando é um pouco menor que 1,6 e o expoente polarizado diz que 1,6 deve ser dividido por 16. (É 011 1101 1 em binário, que é 123 em decimal.) O expoente verdadeiro é 123 - 127 = -4, o que significa que o fator pelo qual multiplicar é 2-4 = 1/16. O significando armazenado é arredondado no último bit na tentativa de representar o número não representável da forma mais precisa possível. (A razão pela qual 1/10 e 1/100 não são exatamente representáveis em binário é semelhante à razão pela qual 1/3 não é exatamente representável em decimal.)

    Valor Fórmula Representação binária Hexadecimal
    0,1 1,6 * 2-4 0011 1101 1100 1100 1100 1100 1100 1101 0x3DCCCCCD
  • Zero é um caso especial. Ele usa a fórmula para o mínimo valor positivo possível representável, que é todos zeros.

    Valor Fórmula Representação binária Hexadecimal
    0 1 * 2-128 0000 0000 0000 0000 0000 0000 0000 0000 0x00000000

Confira também

Por que números de ponto flutuante podem perder a precisão