Introdução ao ponto flutuante

Visão geral

O que é ponto flutuante?

Existem dois tipos de números:

  • ponto fixo onde um certo número de dígitos está disponível antes e depois do ponto de base.
  • ponto flutuante onde um certo número de dígitos está disponível para a mantissa e para o expoente.

Um exemplo usando dígitos decimais com três casas decimais antes do ponto decimal e duas casas decimais após a casa decimal:

  • 0 seria representado como 000,00
  • 0,123 seria representado como 000,12
  • 0,00123 seria representado como 000,00
  • 1 seria representado como 001,00
  • 1.123 seria representado como 001.12
  • 1,00123 seria representado como 001,00
  • 123,456 seria representado como 123,45
  • 1234,56 é um erro porque seria armazenado como 234,56 e isso está errado

Um exemplo usando dígitos decimais com cinco casas decimais para a mantissa e uma casa decimal para o expoente:

  • 0 pode ser representado como 0,00000 x 10^0
  • 0,1 pode ser representado como 0,10000 x 10^0
  • 0,0000123456 pode ser representado como 0,12345 x 10^-4
  • 0,000000000123456 pode ser representado como 0,12345 x 10^-9
  • 0,00000000001 é um erro porque o expoente não é grande o suficiente para armazenar o número
  • 1 pode ser representado como 0,10000 x 10^1
  • 1,123 pode ser representado como 0,11230 x 10^1
  • 1,00123 pode ser representado como 0,10012 x 10^1
  • 123,45678 pode ser representado como 0,12345 x 10^2
  • 123456789.1 pode ser representado como .12345 x 10^9
  • 1000000000 é um erro porque o expoente não é grande o suficiente para armazenar o número

Portanto, um número de ponto flutuante pode representar números com magnitudes muito diferentes (0,000000000123456 e 123456789,1) com a mesma precisão relativa.

Os números de ponto fixo são úteis quando um determinado número de casas decimais é sempre necessário, independentemente da magnitude do número (dinheiro, por exemplo). Os números de ponto flutuante são úteis quando a magnitude varia e a precisão ainda é necessária. Por exemplo: para um engenheiro rodoviário, as distâncias são medidas em metros e 0,01 metro é insignificante, mas para um projetista de microchips a diferença entre 0,0000001 metros e 0,000000001 metros é enorme - e um físico pode precisar usar números enormes e muito, muito números minúsculos no mesmo cálculo. Precisão em muitas magnitudes diferentes é o que torna os números de ponto flutuante úteis.

Como funciona

Computadores não usam decimal - eles usam binário e isso causa problemas para ponto flutuante porque nem todo número decimal pode ser representado exatamente por um número de ponto flutuante e isso introduz erros de arredondamento nos cálculos.

Tendo feito todos os exemplos em decimal é importante notar que por serem binários, ao invés de armazenar um número de ponto flutuante como uma soma de frações decimais:

123.875 = 1/10^-2 + 2/10^-1 + 3/10^0 + 8/10^1 + 7/10^2 + 5/10^3

computadores armazenam números de ponto flutuante como uma soma de frações binárias:

123.875 = 1/2^-6 + 1/2^-5 + 1/2^-4 + 1/2^-3 + 1/2^-1 + 1/2^0 + 1/2^1 + 1/2^2 + 1/2^3

Existem muitas maneiras diferentes de armazenar padrões de bits que representam essas frações, mas a que a maioria dos computadores usa agora é baseada no padrão IEEE-754. Possui regras para armazenar representações decimais e binárias e para tipos de dados de diferentes tamanhos.

A maneira como os números normais são armazenados usando o padrão IEEE é:

  • um bit para o sinal - armazenado no MSB, 1 significa negativo e 0 significa positivo
  • alguns bits para o expoente - o viés é subtraído para obter expoentes positivos e negativos
  • alguns bits para a mantissa - dígitos após a casa decimal com um 1 implícito antes da casa decimal.

Para permitir um underflow mais gradual, os números desnormalizados (quando os bits do expoente são todos zero) são tratados especialmente: o expoente é definido como -126 e o ​​1 implícito à esquerda antes da casa decimal NÃO é adicionado à mantissa.

Números de ponto flutuante IEEE-754 de 32 bits

Para um número normal de ponto flutuante IEEE-754 de 32 bits:

  • bit 32 é o sinal
  • bits 24-31 são o expoente - a polarização é 127
  • bits 1-23 são a mantissa

Assim, um número normal é calculado como:

-1^sign * 2^(exponent-bias) * 1.mantissa

Se o padrão de bits fosse:

0 10000101 11101111100000000000000

Então o valor é:

-1^0 * 2^(133-127) * 1.111011111
-1^0 *     2^6     * (1 + 1/2 + 1/4 + 1/8 + 1/32 + 1/64 + 1/128 + 1/256 + 1/512)
   1 *      64     * 991/512
         123.875

Existem alguns valores especiais:

0 11111111 11111111111111111111111 = NaN
0 11111111 00000000000000000000000 = +infinity
1 11111111 00000000000000000000000 = -infinity
0 00000000 00000000000000000000000 = +Zero
1 00000000 00000000000000000000000 = -Zero

Especificações do formato IEEE-754 de 32 bits podem ser encontradas em:

  • http://floating-point-gui.de/formats/fp
  • https://en.wikipedia.org/wiki/Single-precision_floating-point_format
  • https://en.wikipedia.org/wiki/IEEE_floating_point