O ponto decimal não é explicitamente armazenado em nenhum lugar; isso é um problema de exibição.
A explicação a seguir é uma simplificação; Estou deixando de fora muitos detalhes importantes e meus exemplos não devem representar nenhuma plataforma do mundo real. Ele deve fornecer uma amostra de como os valores de ponto flutuante são representados na memória e os problemas associados a eles, mas você deseja encontrar fontes mais autorizadas, como o que todo cientista da computação deve saber sobre aritmética de ponto flutuante .
Comece representando um valor de ponto flutuante em uma variante da notação científica, usando a base 2 em vez da base 10. Por exemplo, o valor 3.14159 pode ser representado como
0,7853975 * 2 2
0,7853975 é o significando , também conhecido como mantissa; é a parte do número que contém os dígitos significativos. Este valor é multiplicado pela base 2 elevada à potência de 2 para obter 3,14159.
Os números de ponto flutuante são codificados armazenando o significando e o expoente (junto com um bit de sinal).
Um layout típico de 32 bits se parece com o seguinte:
3 32222222 22211111111110000000000
1 09876543 21098765432109876543210
+-+--------+-----------------------+
| | | |
+-+--------+-----------------------+
^ ^ ^
| | |
| | +-- significand
| |
| +------------------- exponent
|
+------------------------ sign bit
Como tipos inteiros assinados, o bit de ordem superior indica sinal; 0 indica um valor positivo, 1 indica negativo.
Os próximos 8 bits são usados para o expoente. Os expoentes podem ser positivos ou negativos, mas em vez de reservar outro bit de sinal, eles são codificados de forma que 10000000 represente 0, portanto 00000000 represente -128 e 11111111 represente 127.
Os bits restantes são usados para o significando. Cada bit representa uma potência negativa de 2 contando da esquerda, portanto:
01101 = 0 * 2 -1 + 1 * 2 -2 + 1 * 2 -3 + 0 * 2 -4 + 1 * 2 -5
= 0,25 + 0,125 + 0,03125
= 0,40625
Algumas plataformas assumem um bit inicial "oculto" no significando que é sempre definido como 1, portanto, os valores no significando estão sempre entre [0,5, 1). Isso permite que essas plataformas armazenem valores com uma precisão um pouco maior (mais sobre isso abaixo). Meu exemplo não faz isso.
Portanto, nosso valor de 3,14159 seria representado como algo como
0 10000010 11001001000011111100111
^ ^ ^
| | |
| | + --- significando = 0,7853975 ...
| |
| + ------------------- expoente = 2 (130 - 128)
|
+ ------------------------- sign = 0 (positivo)
valor = -1 (sinal) * 2 (expoente) * (significando)
valor = -1 0 * 2 2 * 0,7853975 ...
valor = 3.14159 ...
Agora, algo que você notará se somar todos os bits no significado é que eles não totalizam 0,7853975; eles realmente chegam a 0,78539747. Não há bits suficientes para armazenar exatamente o valor ; só podemos armazenar uma aproximação. O número de bits no significando determina a precisão ou quantos dígitos significativos você pode armazenar. 23 bits nos fornece aproximadamente 6 dígitos decimais de precisão. Os tipos de ponto flutuante de 64 bits oferecem bits suficientes no significado e fornecem aproximadamente 12 a 15 dígitos de precisão. Mas esteja ciente de que existem valores que não podem ser representados exatamente, não importa quãomuitos bits que você usa. Assim como valores como 1/3 não podem ser representados em um número finito de dígitos decimais, valores como 1/10 não podem ser representados em um número finito de bits. Como os valores são aproximados, os cálculos com eles também são aproximados e os erros de arredondamento se acumulam.
O número de bits no expoente determina o intervalo (os valores mínimo e máximo que você pode representar). Porém, à medida que você avança em direção aos seus valores mínimos e máximos, o tamanho da diferença entre valores representáveis aumenta. Ou seja, se você não puder representar exatamente valores entre 0,785397 e 0,785398, também não poderá representar exatamente valores entre 7,85397 e 7,85398 ou valores entre 78,5397 e 78,5398 ou valores entre 785397,0 e 785398,0. Tenha cuidado ao multiplicar números muito grandes (em termos de magnitude) por números muito pequenos.