FUNDAMENTALS - CONCEITO DE FLOATING POINT NUMBER
Tags: programming, beginners, computerscience, math
Published: 2023-02-25 09:09:30

## Introdução
Pode parecer algo simples e cotidiano, mas os números fracionados/racionais, como `1.5`, `0.25`, `0.000005` eram um desafio para os computadores operarem e representarem. Então irei apresentar os conceitos básicos de como chegamos ao que conhecemos hoje como float number e as vantagens e desvantagens (ou quase).

## Como computadores representam números
Quando pensamos na representação de números para computadores o sistema binário é essencial, pois 1s e 0s podem ser interpretados como "on" e "off", sendo cada um desses estados um bit de informação, perfeito para máquinas. 


![máquinas entendem 0s e 1s](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/br1tzyap4t51wwxn15fv.png)

Então poderíamos representar os números 8 e 4 desta maneira, respectivamente, em binário `1000`, `100`. Agora que conseguimos representa-los para o computador, ele pode começar a realizar operações, tais como uma adição {% katex inline %}1000 + 100 = 1100{% endkatex %} ou {% katex inline %}8 + 4 = 12{% endkatex %}. 

De fato, as máquinas não tem dificuldades na representação de números inteiros ou mesmo em realizar operações matemáticas, contudo como poderíamos fazer o mesmo com números fracionados ?

## Fixed point number
Podemos representar números fracionados em binário da mesma maneira que números decimais `10.2 -> 1010.10`. O principal para a representação desses números é o ponto decimal, separando a parte inteira da fracionada. Contudo, este ponto é algo "imaginário", conseguimos representar sem problemas no papel, mas com máquinas é diferente, pois há apenas 0s e 1s para se trabalhar. 

Mas gigantes descobriram que os computadores poderiam representar números fracionados da seguinte maneira:

    
	// vamos imaginar que temos 12 bits de informação
	 000000000000
	
	// separamos 8 bits para a parte inteira do número
	 [00000000]0000
	 
	// e 4 bits para representar a parte fracionada
	 [00000000][0000]

Logo, poderíamos representar o número 10.125, assim: 

    // convertemos para binário
     10.125 -> 1010.001
    
    // adicionamos zeros até dá os 8 bits da parte inteira
     00001010
    
    // e os 4 bits representando a parte fracionada
	 00001010 0010
    
***OBS:*** cada coluna dos 4 bits da parte fracionada representam os seguintes valores {% katex inline %}\frac{1}{2}{% endkatex %},  {% katex inline %}\frac{1}{4}{% endkatex %}, {% katex inline %}\frac{1}{8}{% endkatex %}, {% katex inline %}\frac{1}{16}{% endkatex %}.


![isso nos limita muito na representação dos números](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9icd8l11f14fmm648hoa.png)

Entretanto, se você necessitar de um número muito preciso, o método fixed point não será o melhor, pois a quantidade de bits limita o quão pequeno ou grande o número pode ser, logo perdendo precisão, contudo ele é ótimo para sistemas em tempo real que necessitam de velocidade e não precisão.

## Floating point number
Lembram-se do conceito de **notação científica** ? ...não se preocupe, vou te refrescar a memória. 

Temos um número real **N** que deve ser {% katex inline %}1 >= N < 10{% endkatex %}, podemos chamar essa parte de **mantissa**, também temos um inteiro **n**, o **expoente**, nos informando quantas colunas/casas o ponto deve andar para representar o número de fato. 

Então ficaria assim: {% katex inline %}6.25 * 10^{9} = 6250000000{% endkatex %}, desta maneira conseguimos representar números colossais, como a velocidade da luz no vácuo {% katex inline %}3,0 * 10⁸ \frac{m}{s}{% endkatex %} ou mesmo a massa de um elétron {% katex inline %}9,11 * 10^{-31} kg{% endkatex %}. 	
Flexível, né ? E é com essa mesma premissa que os floating point numbers se utilizam para representar números fracionados. 

Vamos entender isso de forma simplificada, pensando em um sistema de 32 bits podemos utilizar 1 bit como sinal, positivo ou negativo, 8 bits para o expoente, que definirá onde nosso ponto irá estar, separando a parte inteira da fracionada, e 23 bits para a mantissa, o número de dígitos em si. 

Com isso podemos representar o número 10.5 da seguinte maneira 

      
    // convertemos para binário 
	    10.5 -> 1010.1
	    
	// passamos para notação científica 
	    1010.1 -> 1.0101 e3 	// colocamos o ponto após o primeiro digito e contamos
							    // quantas casas há depois do ponto até a parte fracionada
							    // onde *e* é o expoente, nos dizendo a quantidade de casas
							    // que o ponto tem que pular.
							    
       
    // agora vamos somar o expoente 3 com 127
    // que nos permite representar números de -127 até 127
	    3 + 127 = 130 -> 10000010  // agora temos o expoente
	    
    // acrescente zeros até dá os 24 bits da mantissa
	    1.0101 -> 1.0101000000000000000000
	    
    // remova o digito antes do ponto, ficando 23 bits para a mantissa
	    1.0101000000000000000000 -> 0101000000000000000000
  
Resultado

| Sinal      | Expoente |Mantissa|
| ----------- | ----------- | ----------- |
| 0      | 10000010       |0101000000000000000000|

Agora podemos pegar a mantissa e pular a quantidade de colunas/casas a partir do primeiro digito que o expoente nos informa.
	
![o ponto parece está flutuando de uma coluna para outra](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2o4is16exzjdmjlc7n1o.png)
	
 Desta maneira, computadores conseguem representar números fracionados com maior precisão e realizar operações, como adição, subtração e entre outras.
 
 O fato de este padrão (estabelecido pelo IEEE) se chamar numero de ponto flutuante se dá pelo fato das casas/colunas que pulamos para estabelecer o ponto imaginário que divide a parte inteira da fracionada.