Vírgula flutuante

Origem: Wikipédia, a enciclopédia livre.

Vírgula flutuante (original em alemão Gleitkomma ou Fließkomma) ou ponto flutuante (do inglês floating point) é um formato de representação digital de números racionais, que é usada nos computadores.

Generalidades sobre vírgula flutuante

Ao falar em números reais a visualização vinda à cabeça é:

Representação de um número fracionário.

No entanto, essa representação custa caro, em termos de processamento e armazenamento ao computador havendo a necessidade de utilizar uma outra maneira que favoreça tais tarefas. Para trabalhar com a parte fracionária de forma satisfatória, usa-se a representação por vírgula flutuante.

Essa representação baseia-se no deslocamento da vírgula de forma que se obtenha um número menor ou próximo de 1. Esse deslocamento é feito por meio de notação científica. Esclarecendo: o número 25,456 em notação corresponde ao 0,25456 x 102.

O exemplo acima tinha como base a decimal, no entanto o computador trabalha com a base 2 (binários – 0 e 1). Então um número binário 11,011 em notação corresponde ao 0,11011 x 22. Esse processo de transcrever um número em notação científica recebe o nome de normalização, portanto 0,11011 x 22 está normalizado.

De forma geral, representa-se um número em vírgula flutuante da seguinte forma:

+- M X B+-e

Onde:

Esquematicamente tem-se [1]:

Desta forma é possível cobrir um largo espectro de números, maximizando o número de bits significativos e consequentemente a precisão da aproximação. Esta forma de representação foi criada por Konrad Zuse para os seus computadores Z1 (1937) e Z3 (1941), batizada, então, de Gleitkommazahl (literalmente número com vírgula escorregante).[carece de fontes?]

O número de bits alocados para representar a mantissa e o expoente depende da norma utilizada.

Para obter o número em vírgula flutuante converte-se o número para a base na qual será armazenado, normaliza-o e por fim separa-se mantissa, expoente e sinais.

Exemplo[2]:

Assumindo:

  • 1 bit para o sinal do número
  • 1 bit para o sinal do expoente
  • 4 bits para o expoente
  • 10 bits para a mantissa

Represente o número 5,7510 em vírgula flutuante. O número em questão encontra-se na base 10, portanto é preciso convertê-lo para binário (base 2), base entendida pelo computador. 5,7510 => 101,112

Normalizando tem-se: 0,10111 x 23

Separando sinais, mantissa e expoente tem-se:

  • Sinal do número: (+) 0
  • Sinal do expoente: (+) 0
  • Expoente: 011 (3)
  • Mantissa: 10111

Portanto tem-se: 00001100000101112

A maioria dos sistemas que operam com vírgula flutuante utilizam representações definidas na norma IEEE 754.

O padrão IEEE para aritmética de vírgula flutuante (IEEE 754) é o padrão mais amplamente utilizado, e é seguido por muitos CPU e melhorias FPU. A norma define formatos para representar números de vírgula flutuante (incluindo zero) e os valores não normalizados, bem como os valores especiais infinito e NaN, com um conjunto de operações de vírgula flutuante que trabalham com esses valores. Também especifica quatro modos de arredondamento e cinco exceções (inclusive quando essas exceções ocorrem é o que acontece nesses momentos). A Norma IEEE 754-2008 define os formatos adequados para representar números em vírgula flutuante de precisão simples (32 bits) e de precisão dupla (64 bits). O título completo da norma é o padrão IEEE para Aritmética Binária de Vírgula Flutuante (ANSI / IEEE Std 754-1985), e também é conhecido pelo IEC 60559:1989, Binary floating-point arithmetic for microprocessor systems (originalmente o número de referência era IEC 559:1989).[3][4]

O formato de vírgula flutuante de precisão simples (32 bits) consiste num bit de sinal (s), 8 bits de expoente (e) e uma mantissa de 23 bits (m). O bit de sinal (s) é 0 (zero) para números positivos e 1 para números negativos. O campo de expoente (e) corresponde à soma de 127 com o expoente de base 2 do número representado. O campo de mantissa (m) corresponde à parte fracionária da mantissa do número representado. Considera-se sempre a mantissa normalizada entre 1 e 2. Desta forma a sua parte inteira é sempre apenas um bit igual a 1 (um) que não é necessário representar.

v = S × M × 2E

Onde:

S = 1 − 2 × s

M = 1.m = 1 + m × 2−23

E = e − 127

Problemas com o uso de ponto flutuante

Em geral, o conjunto de números representáveis pela notação de ponto flutuante é semelhante o suficiente ao conjunto dos números reais para a maior parte das aplicações, o que no entanto frequentemente leva programadores a desconsiderar a importância da análise numérica adequada sobre os resultados obtidos. Há muitas inconsistências entre o comportamento dos números de ponto flutuante em base 2 (binário) e os números reais, mesmo em casos muito simples (como a fração decimal 0,1, que por em binário ser uma dízima periódica, não pode ser expressa de maneira exata por qualquer representação binária finita). As principais causas de erro com uso de ponto flutuante são:

  • Arredondamento de valores (por exemplo, 0,1);
  • Arredondamento de operações aritméticas (por exemplo, 0.1 + 0.2 = 0.30000000000000004[5]);
  • Absorção de valores de diferentes níveis de magnitude (por exemplo, 1e8f + 1 - 1e8f = 0[6]);
  • Cancelamento (por exemplo, a subtração de dois números muito próximos);
  • Overflow, ou transbordamento (com relatórios de resultado infinito);
  • Underflow (devolve um 0, ou o número subnormal, menor do que o menor permitido);
  • Operação impossível (por exemplo, raiz quadrada de um números negativos resultando em NaN - Not a Number);
  • Necessidade de deslocamento dinâmico do expoente[7].

A notação de ponto flutuante é particularmente adequada quando se almeja uma maior amplitude do domínio representável em detrimento da constância da precisão, cenário frequente em aplicações científicas e de engenharia. Instituições financeiras, porém, frequentemente dão preferência à notação de ponto fixo almejando uma precisão constante.

Propriedades de aritmética de ponto flutuante

Esta aritmética tem duas diferenças fundamentais: ela não é, necessariamente, nem associativa nem distributiva:

.

Ou seja, a ordem em que você estiver executando operações de ponto flutuante pode influenciar o resultado. Isto é importante para a análise numérica, uma vez que duas fórmulas matematicamente equivalentes podem ter resultados e precisões diferentes. Por exemplo, na maioria das aplicações de ponto flutuante, 1,0 + (10100 + -10100) resulta em 1,0, enquanto que (1,0 + 10100) + -10100 dá 0,0[carece de fontes?]

Exemplos

A fração decimal:

0,125

é representada por: 1/10 + 2/100 + 5/1000. Da mesma forma, a fração binária:

0,001

tem valor: 0/2 + 0/4 + 1/8. Os dois valores são idênticos, sendo o primeiro escrito na base 10 e o segundo na base 2.

Valor S × M × 2E s m e IEEE 754 - Single Precision
1 1 × 1 × 20 0 0x00 127 0 0111 1111 000 0000 0000 0000 0000 0000
-1 -1 × 1 × 20 1 0x00 127 1 0111 1111 000 0000 0000 0000 0000 0000
0,5 1 × 1 × 2−1 0 0x00 126 0 0111 1110 000 0000 0000 0000 0000 0000
-0,5 -1 × 1 × 2−1 1 0x00 126 1 0111 1110 000 0000 0000 0000 0000 0000
0,15625 1 × 1,25 × 2−3 0 0x200000 124 0 0111 1100 010 0000 0000 0000 0000 0000

Tabela com exemplos de números reais de três dígitos significativos e sua representação em notação científica:

Número real Notação científica
0.000000000000000438 4.38× 10−16
0.000000438 4.38× 10−7
0.00438 4.38× 10−3
0.438 4.38× 10−1
4.38 4.38× 100
43.8 4.38× 101
4380.0 4.38× 103
43800000.0 4.38× 107
43800000000000000.0 4.38× 1016

Valores Especiais

As notações com os bits do campo expoente (e) todos a um ou todos a zero são reservadas para valores especiais. O zero é representado com e=0 e m=0. Outros valores de m com e=0 indicam números não normalizados. Nestas casos considera-se a mantissa entre 0 e 1.

IEEE 754 - Single Precision Valor
s e m
0 0000 0000 000 0000 0000 0000 0000 0000 +0 Zero
1 0000 0000 000 0000 0000 0000 0000 0000 -0
0 1111 1111 000 0000 0000 0000 0000 0000 +Inf Infinito Positivo
1 1111 1111 000 0000 0000 0000 0000 0000 -Inf Infinito Negativo
0 1111 1111 010 0000 0000 0000 0000 0000 +NaN Not a Number
1 1111 1111 010 0000 0000 0000 0000 0000 -NaN

Implementação em Linguagens de Programação

Muitas frações decimais não podem ser representadas exatamente como frações binárias finitas. Por consequência, diversos números armazenados na máquina em váriaveis do tipo ponto flutuante (float, double, real) são apenas aproximações.[8]

Considere, por exemplo, a fração 1/3. Uma aproximação decimal seria:

0,3
ou, melhor:
0,33
ou, ainda melhor:
0,333

e assim por diante. Não existe uma fração finita capaz de resultar em exatamente 1/3.

Um outro exemplo interessante é a fração 1/10. Em muitas linguagens de programação, apesar de rotinas de impressão mostrar o valor 0,100000, se exibirmos o número com maior precisão (por exemplo, 20 casas decimais), veremos que o valor real armazenado será algo aproximado de:

0,10000000149001612000 (o valor pode mudar segundo o hardware e a linguagem utilizada).

Assim, ao programar é preciso ter cuidado com números em ponto flutuante, em especial com acumuladores e comparações.

Referências

  1. Prof. MSc. Steinmacher,Igor, 2009, Imagem esquemática do Slide sobre Representação de Dados-Pontos Flutuantes
  2. Prof. MSc. Steinmacher, Igor, 2009, Exemplo retirado do Slide sobre Representação de Dados-Pontos Flutuantes
  3. http://pubs.opengroup.org/onlinepubs/009695399/frontmatter/refdocs.html
  4. http://www.ajdesigner.com/fl_ieee_754_word/ieee_32_bit_word.php
  5. Wiffin, Erik (19 de outubro de 2020). «0.30000000000000004». Consultado em 20 de novembro de 2020 
  6. Zitoun, Heytem; Michel, Claude; Rueher, Michel; Michel, Laurent (7 de julho de 2018). «Sub-domain Selection Strategies For Floating Point Constraint Systems». Springer. International Conference on Principles and Practice of Constraint Programming. Consultado em 20 de novembro de 2011  line feed character character in |titulo= at position 51 (ajuda)
  7. «LABVIEW NXG 5.0 MANUAL». NATIONAL INSTRUMENTS CORP. 9 de agosto de 2019. Consultado em 20 de novembro de 2020 
  8. «Floating Point Arithmetic: Issues and Limitations» (em inglês). Python v2.6.4 documentation 
Ícone de esboço Este artigo sobre informática é um esboço. Você pode ajudar a Wikipédia expandindo-o.