Vírgula flutuante e IEEE 754
Vírgula fixa em formato Q, normais e subnormais, arredondamento e operações IEEE 754.
Guardar o inteiro 26 e interpretá-lo em unidades de dá . Nenhum bit da palavra assinala a vírgula, pois essa escala faz parte do acordo entre o circuito e o programa; na vírgula fixa, o passo é constante, enquanto na vírgula flutuante um expoente guardado com o significando altera a escala e o espaçamento entre valores.
Convenção Qm.n
Usamos com bits para a parte inteira incluindo o sinal e bits fracionários; a largura total é . O inteiro está em complemento para dois e representa
O intervalo é e a resolução é . Em , os 8 bits representam de a , em passos de .
Para codificar em , calcula . Em 8 bits, . Para descodificar D4, lê primeiro em complemento para dois e só depois divide por 16.
Escolher um formato
Queremos medir valores entre e com passo não superior a . Precisamos de : dá . Para o intervalo, só chega a menos de 16, enquanto chega a menos de 32, portanto , com 13 bits, satisfaz ambas as condições.
Se a palavra disponível só tiver 12 bits, não podemos manter essas duas escolhas. Temos de reduzir o intervalo, aceitar um passo maior ou aumentar a largura, porque a precisão e o intervalo competem pelos bits.
Um valor não múltiplo da resolução exige arredondamento ou truncatura. Em , : arredondar para o inteiro mais próximo dá e valor , enquanto truncar para zero dá e valor . Indica a política usada.
Adição e mudança de escala
Com a mesma escala, somamos os inteiros: . Em , é 24 e é , por isso a soma 12 representa ; o teste de overflow é o da palavra inteira com sinal.
Se as escalas diferirem, alinha-as primeiro. Converter de para exige multiplicar o código por , acrescentando dois bits fracionários. Converter no sentido inverso perde bits e pode exigir arredondamento. Um deslocamento à direita aritmético de negativos arredonda para baixo; não equivale sempre a truncar para zero.
Por exemplo, soma 1,5 guardado com quatro bits fracionários a 0,25 guardado com seis. Os códigos são 24 e 16; na escala de seis bits, o primeiro passa a . Agora representa , enquanto somar diretamente 24+16 misturaria unidades diferentes.
Multiplicação e divisão
Se e , o produto inteiro tem escala . Para voltar à escala inicial, calcula com largura suficiente para o produto intermédio.
Em , usa . Dividindo por 16 obtemos , que representa . O produto não cabe em 8 bits, embora o resultado final caiba. Fazer a multiplicação já em 8 bits destruiria o resultado.
Para obter na escala , com , calcula com numerador alargado e arredondamento definido
como em , que dá , ou seja, 2.
Com escalas nas entradas e no resultado, o produto requer um deslocamento de posições à direita, se esse valor for não negativo. Separar a escala da largura evita confundir overflow com perda de precisão.
Campos e valores
O sinal vale 0 para positivo e 1 para negativo. A tabela indica o número de bits de cada campo e o bias do formato.
| Formato | Sinal | Expoente | Fração | Bias |
|---|---|---|---|---|
| binary32 | 1 | 8 | 23 | 127 |
| binary64 | 1 | 11 | 52 | 1023 |
| bfloat16 | 1 | 8 | 7 | 127 |
Aqui e são os inteiros sem sinal lidos dos respetivos campos. é o expoente com todos os bits a 1: 255 em binary32. O bias é a constante subtraída a para obter o expoente real. é o número de bits da fração.
Se , o número é normal, com
onde o 1 antes da vírgula é implícito; assim binary32 tem 24 bits de precisão no significando dos normais.
Se , não há esse 1, com
Com obtemos um subnormal. Com obtemos ou .
Se todos os bits do expoente forem 1, o valor depende só da fração: significa infinito e significa NaN, not a number. NaN não é um número muito grande; é o código para resultados sem valor numérico.
Binary32 e binary64 são formatos IEEE 754. Bfloat16 usa a disposição indicada na tabela; não se deve inferir que qualquer operação ou conversão de bfloat16 tenha as mesmas regras de um ambiente IEEE 754 completo. Nos exemplos de arredondamento abaixo usamos explicitamente o modo mais próximo, com empates para par.
Codificar um valor
Codifica em binary32. O módulo é , portanto , e a fração é 10101 seguida de 18 zeros:
1 | 10000010 | 10101000000000000000000
Agrupar em grupos de quatro bits dá 0xC1540000. Para descodificar, reconstrói . Não interpretes a palavra completa em complemento para dois.
Limites e espaçamento
Em binary32, o menor normal positivo é e o menor subnormal positivo é . O maior finito é . Os subnormais mantêm passos de perto de zero, com menos bits significativos à medida que o valor diminui.
No intervalo , os normais binary32 têm espaçamento . Entre 1 e 2 é ; entre 2 e 4 é . Em bfloat16, o menor representável maior que 2 é , porque o expoente tem a mesma largura de binary32 mas a precisão é muito menor.
Somar e subtrair
Para somar , escreve e . Os bits só podem ser somados por coluna quando têm os mesmos pesos, por isso conserva o expoente 2 e desloca o segundo significando duas posições à direita:
1,0110 × 2² 5,5
+ 0,0101 × 2² 1,25
──────────
1,1011 × 2² 6,75
O zero acrescentado ao primeiro significando só completa a coluna. O resultado já está normalizado, pois o significando está entre 1 e 2.
Subtrair usa o mesmo alinhamento: dá . Depois de uma quase anulação, pode ser preciso normalizar deslocando para a esquerda.
No formato finito, conserva bits adicionais durante a conta e arredonda no fim. O modo usual é o mais próximo, com empates para o significando cujo último bit conservado é par. Truncar sempre não implementa esta regra.
Um modelo pequeno com três bits de fração ajuda a ver um empate. Entre 1 e 2, os números avançam de 1/8 em 1/8; o valor fica a meio de 1,000 e 1,001, por isso escolhemos 1,000, cujo último bit é 0. Já fica a meio de 1,001 e 1,010, por isso escolhemos 1,010. Empate para par pode arredondar para cima ou para baixo; este modelo serve apenas para explicar a regra, pois binary32 conserva 23 bits de fração.
Multiplicar e perder precisão
Na multiplicação, trata cada campo em separado: XOR dos sinais, soma dos expoentes reais e produto dos significandos. Para , os significandos dão , com expoente 1, ou seja, . Se o produto dos significandos atingir 2, divide-o por 2 e aumenta o expoente em 1.
Overflow pode produzir infinito; resultados demasiado pequenos podem tornar-se subnormais ou zero. Reduzir a precisão também exige arredondar, mesmo dentro do intervalo: não tem representação binária finita, por isso binary64 guarda-o arredondado a 52 bits e a passagem a binary32 arredonda de novo a 23 bits. No exercício de bfloat16 do volume 1, a ausência de subnormais é uma hipótese local desse enunciado, não uma propriedade geral do formato.
A adição não é associativa em geral. Em binary32, arredonda para , pois o passo é 2 e o empate conserva o último bit par. Assim , mas .
11 bit100000108 bits1010100000000000000000023 bits- Classe
- Normal
- Expoente armazenado
- 130
- Expoente real
- 3
- Significando
- 1,65625
- Valor
- −13,25
A visualização separa sinal, expoente e fração e aplica as regras de binary32, sem efetuar uma nova operação aritmética entre floats. Os bits são exatos; a escrita decimal de valores muito pequenos ou grandes é uma aproximação. Para NaN e infinito, a fórmula dos números finitos não se aplica.
Exercícios
Escolher intervalo e passo
Escolhe o menor formato Qm.n com sinal que representa de -12 a +12 com passo não superior a 1/32. Indica a largura.
Pista
Escolhe n pelo passo e m pelo intervalo.
Mais uma pista
m inclui o bit de sinal; Q4 não chega a +12.
Solução
dá passo 1/32. dá máximo menor que 8, insuficiente; dá máximo . Logo Q5.5, largura 10 bits. Os extremos pedidos são múltiplos do passo e ficam no intervalo.
Confere a tua resposta:
- Q5.5, largura 10 bits.
- Confirma intervalo e passo 1/32.
Erros frequentes
Não escolhas m=4 contando apenas os bits da magnitude.
Escala do produto
Em Q4.4, calcula através dos códigos inteiros. Explica a largura do intermédio.
Pista
Os códigos são os valores multiplicados por 16.
Mais uma pista
O produto tem inicialmente 8 bits fracionários.
Solução
X=40, Y=-20. O produto inteiro é -800, com escala 1/256. Para voltar a Q4.4, divide por 16: Z=-50, representando -3,125. -800 não cabe em 8 bits, pelo que o produto tem de ser calculado em largura maior. O resultado final -50 cabe.
Confere a tua resposta:
- Códigos 40 e -20; produto intermédio -800.
- Intermédio mais largo que oito bits; código final -50, valor -3,125.
Erros frequentes
Não dividas o produto pela escala antes de o calcular num registo com largura suficiente.
Três regras para um negativo
Converte o código X=-7 de uma escala com n=3 para n=1. Compara truncatura para zero, arredondamento para baixo e arredondamento ao mais próximo.
Pista
O novo código exato seria -7/4.
Mais uma pista
O valor original é -0,875; a nova resolução é 0,5.
Solução
O código ideal é -1,75. Truncar para zero dá -1, valor -0,5. Arredondar para baixo dá -2, valor -1. O mais próximo também dá -2, porque -1 está a 0,125 do original e -0,5 a 0,375. Um shift aritmético por 2 implementa a opção para baixo neste caso.
Confere a tua resposta:
- Códigos -1 para zero; -2 para baixo e mais próximo.
- Relaciona os códigos com valores -0,5 e -1.
Erros frequentes
Para negativos, um shift aritmético não é truncatura para zero.
Codificar binary32
Codifica em binary32. Dá sinal, expoente armazenado, fração e hexadecimal.
Pista
6,5 é 110,1 em binário.
Mais uma pista
Normaliza para 1,101×2².
Solução
, expoente real 2, . A fração é 101 seguida de 20 zeros. A palavra é 0 | 10000001 | 10100000000000000000000, hexadecimal 0x40D00000. A reconstrução é .
Confere a tua resposta:
- Sinal 0, E=129, fração começa por 101.
- Hexadecimal 40D00000 e reconstrução 6,5.
Erros frequentes
O expoente armazenado inclui bias; a fração não guarda o 1 implícito.
Classificar os campos
Classifica 0x80000000, 0x00000001, 0x7F800000 e 0xFFC00000 em binary32.
Pista
Separa expoente e fração antes de usar o sinal.
Mais uma pista
Expoente todo 1 só é infinito quando a fração é zero.
Solução
80000000 é -0; 00000001 é o menor subnormal positivo, ; 7F800000 é +infinito; FFC00000 é NaN, porque E=255 e F é diferente de 0. O sinal 1 não transforma NaN num número negativo ordenável.
Confere a tua resposta:
- Identifica -0, menor subnormal, +infinito e NaN.
- Usa a fração para distinguir NaN de infinito.
Erros frequentes
Nem todo o padrão com expoente máximo é infinito, porque a fração decide entre infinito e NaN.
Precisão local de bfloat16
Qual é a distância entre números bfloat16 consecutivos entre 8 e 16? Qual é o menor representável maior que 8?
Pista
8 corresponde a expoente real 3.
Mais uma pista
Há 7 bits de fração, pelo que o passo é 2^(3−7).
Solução
O passo é . O número seguinte é . O passo não é em todo o intervalo, porque o expoente altera a escala.
Confere a tua resposta:
- Passo 0,0625 e número seguinte 8,0625.
- Usa expoente real 3 e sete bits de fração.
Erros frequentes
Usar o passo perto de 1 em qualquer magnitude ignora o papel do expoente, porque o passo cresce com o intervalo.
Alinhar, somar e normalizar
Faz em binário e . Mostra a normalização.
Pista
Na soma alinha os expoentes; no produto multiplica significandos.
Mais uma pista
3,5 é 1,11×2¹; 0,75 é 1,1×2⁻¹.
Solução
A soma é . O produto é . Ambos têm expansão curta, cabem exatamente em binary32, sem arredondamento adicional.
Confere a tua resposta:
- Soma 4,25; produto 2,625.
- Alinha na soma e normaliza os dois resultados.
Erros frequentes
Não somes expoentes na adição; não conserves significando maior ou igual a 2 sem ajustar o expoente.
Dois empates em binary32
Usa binary32 e arredondamento ao mais próximo, com empates para par. Que valores ficam guardados ao converter os valores exatos e ? Mostra os dois vizinhos de cada valor.
Pista
Os valores exatos estão a meio de dois binary32 consecutivos.
Mais uma pista
O passo entre 1 e 2 é .
Solução
O primeiro fica a meio de e ; escolhemos 1, fração inteira F=0, par. O segundo fica a meio de e ; escolhemos o segundo vizinho, com F=2, par. Portanto os resultados são e . A regra examina o último bit conservado, não o sinal nem o expoente.
Confere a tua resposta:
- Primeiro resultado 1; segundo 1+2^-22.
- Identifica o passo 2^-23 e o bit final par em cada empate.
Erros frequentes
Não arredondes sempre para baixo nem interpretes par como um valor decimal inteiro par.
O bit implícito muda
Descodifica 0x007FFFFF e 0x00800000 em binary32. Qual é a distância entre eles? Explica por que não há um salto grande na passagem de subnormal a normal.
Pista
No primeiro E=0; no segundo E=1.
Mais uma pista
A fórmula do subnormal usa expoente real .
Solução
007FFFFF tem F=, valor . 00800000 tem E=1 e F=0, valor . A diferença é , o mesmo passo dos subnormais. Usar um 1 implícito no primeiro código duplicaria aproximadamente o seu valor.
Confere a tua resposta:
- Maior subnormal (1−2^-23)×2^-126 e menor normal 2^-126.
- Distância 2^-149; muda o bit implícito e não o passo na fronteira.
Erros frequentes
Não uses E−bias nos subnormais nem compares as palavras como inteiros para obter uma diferença de valores reais.