IEEE 754 - IEEE 754

O Padrão IEEE para Aritmética de Ponto Flutuante ( IEEE 754 ) é um padrão técnico para aritmética de ponto flutuante estabelecido em 1985 pelo Instituto de Engenheiros Elétricos e Eletrônicos (IEEE). O padrão abordou muitos problemas encontrados nas diversas implementações de ponto flutuante que os tornavam difíceis de usar de forma confiável e portátil . Muitas unidades de ponto flutuante de hardware usam o padrão IEEE 754.

O padrão define:

  • formatos aritméticos: conjuntos de dados de ponto flutuante binários e decimais , que consistem em números finitos (incluindo zeros com sinais e números subnormais ), infinitos e valores especiais "não é um número" ( NaNs )
  • formatos de intercâmbio: codificações (strings de bits) que podem ser usados ​​para trocar dados de ponto flutuante de uma forma eficiente e compacta
  • regras de arredondamento: propriedades a serem satisfeitas ao arredondar os números durante a aritmética e as conversões
  • operações: operações aritméticas e outras (como funções trigonométricas ) em formatos aritméticos
  • tratamento de exceções: indicações de condições excepcionais (como divisão por zero , estouro, etc. )

IEEE 754-2008 , publicado em agosto de 2008, inclui quase todo o padrão IEEE 754-1985 original , mais o padrão IEEE 854-1987 para aritmética de ponto flutuante independente de Radix . A versão atual, IEEE 754-2019, foi publicada em julho de 2019. É uma pequena revisão da versão anterior, incorporando principalmente esclarecimentos, correções de defeitos e novas operações recomendadas.

Desenvolvimento padrão

O primeiro padrão para aritmética de ponto flutuante, IEEE 754-1985 , foi publicado em 1985. Ele cobria apenas aritmética de ponto flutuante binário.

Uma nova versão, IEEE 754-2008 , foi publicada em agosto de 2008, após um processo de revisão de sete anos, presidido por Dan Zuras e editada por Mike Cowlishaw . Ele substituiu o IEEE 754-1985 (aritmética de ponto flutuante binário) e o padrão IEEE 854-1987 para aritmética de ponto flutuante independente de Radix . Os formatos binários no padrão original estão incluídos neste novo padrão junto com três novos formatos básicos, um binário e dois decimais. Para estar em conformidade com o padrão atual, uma implementação deve implementar pelo menos um dos formatos básicos como formato aritmético e formato de intercâmbio.

O padrão internacional ISO / IEC / IEEE 60559: 2011 (com conteúdo idêntico ao IEEE 754-2008) foi aprovado para adoção pelo JTC1 / SC 25 sob o Acordo ISO / IEEE PSDO e publicado.

A versão atual, IEEE 754-2019 publicada em julho de 2019, é derivada e substitui a IEEE 754-2008, após um processo de revisão iniciado em setembro de 2015, presidido por David G. Hough e editado por Mike Cowlishaw. Ele incorpora principalmente esclarecimentos (por exemplo, totalOrder ) e correções de defeitos (por exemplo, minNum ), mas também inclui algumas novas operações recomendadas (por exemplo, augmentedAddition ).

O padrão internacional ISO / IEC 60559: 2020 (com conteúdo idêntico ao IEEE 754-2019) foi aprovado para adoção pelo JTC1 / SC 25 e publicado.

Formatos

Um formato IEEE 754 é um "conjunto de representações de valores e símbolos numéricos". Um formato também pode incluir como o conjunto é codificado.

Um formato de ponto flutuante é especificado por:

  • uma base (também chamada de raiz ) b , que é 2 (binária) ou 10 (decimal) no IEEE 754;
  • a precisão p ;
  • um expoente varia de emin a emax , com emin = 1 - emax para todos os formatos IEEE 754.

Um formato compreende:

  • Números finitos, que podem ser descritos por três inteiros: s  = um sinal (zero ou um), c  = um significando (ou coeficiente ) tendo não mais do que p dígitos quando escrito na base b (ou seja, um inteiro no intervalo até 0 para b p  - 1), e q  = um expoente tal que eminq  +  p  - 1 ≤ emax . O valor numérico de tal número finito é (−1) s × c × b q . Além disso, existem dois valores zero, chamados zeros com sinal: o bit de sinal especifica se um zero é +0 (zero positivo) ou −0 (zero negativo).
  • Dois infinitos: + ∞ e −∞.
  • Dois tipos de NaN (não um número): um NaN silencioso (qNaN) e um NaN de sinalização (sNaN).

Por exemplo, se b = 10, p = 7 e emax = 96, então emin = −95, o significando satisfaz 0 ≤ c9 999 999 , e o expoente satisfaz −101 ≤ q ≤ 90. Consequentemente, o menor número positivo diferente de zero que pode ser representado é 1 × 10 −101 , e o maior é 9999999 × 10 90 (9,999999 × 10 96 ), portanto, o intervalo completo de números é de -9,999999 × 10 96 a 9,999999 × 10 96 . Os números - b 1- Emax e b 1- Emax (aqui, -1 × 10 -95 e 1 x 10 -95 ) são os mais pequenos em magnitude () números normais ; números diferentes de zero entre esses números menores são chamados de números subnormais .

Representação e codificação na memória

Alguns números podem ter várias representações de formato exponencial possíveis. Por exemplo, se b  = 10 e p  = 7, então −12,345 pode ser representado por −12345 × 10 −3 , −123450 × 10 −4 e −1234500 × 10 −5 . No entanto, para a maioria das operações, como operações aritméticas, o resultado (valor) não depende da representação das entradas.

Para os formatos decimais, qualquer representação é válida e o conjunto dessas representações é denominado coorte . Quando um resultado pode ter várias representações, a norma especifica qual membro da coorte é escolhido.

Para os formatos binários, a representação é tornada única escolhendo o menor expoente representável permitindo que o valor seja representado exatamente. Além disso, o expoente não é representado diretamente, mas um viés é adicionado para que o menor expoente representável seja representado como 1, com 0 usado para números subnormais. Para números com um expoente na faixa normal (o campo do expoente não sendo nem todos os uns nem todos os zeros), o bit inicial do significando será sempre 1. Consequentemente, um 1 inicial pode estar implícito em vez de explicitamente presente na codificação de memória, e, de acordo com o padrão, a parte explicitamente representada do significando ficará entre 0 e 1. Essa regra é chamada de convenção de bit principal , convenção de bit implícita ou convenção de bit oculto . Esta regra permite que o formato binário tenha um pouco de precisão extra. A convenção de bits iniciais não pode ser usada para os números subnormais, pois eles têm um expoente fora da faixa de expoente normal e escala pelo menor expoente representado como usado para os menores números normais.

Devido à possibilidade de múltiplas codificações (pelo menos em formatos chamados formatos de intercâmbio ), um NaN pode transportar outras informações: um bit de sinal (que não tem significado, mas pode ser usado por algumas operações) e uma carga útil , que se destina ao diagnóstico informações que indicam a origem do NaN (mas a carga útil pode ter outros usos, como NaN-boxing ).

Formatos básicos e de intercâmbio

O padrão define cinco formatos básicos que são nomeados de acordo com sua base numérica e o número de bits usados ​​em sua codificação de intercâmbio. Existem três formatos básicos de ponto flutuante binário (codificados com 32, 64 ou 128 bits) e dois formatos básicos de ponto flutuante decimal (codificados com 64 ou 128 bits). Os binary32 e binary64 formatos são os únicos e duplos formatos de IEEE 754-1985 respectivamente. Uma implementação em conformidade deve implementar totalmente pelo menos um dos formatos básicos.

O padrão também define formatos de intercâmbio , que generalizam esses formatos básicos. Para os formatos binários, a convenção de bits iniciais é necessária. A tabela a seguir resume os menores formatos de intercâmbio (incluindo os básicos).

Nome Nome comum Base Bits ou dígitos significativos Dígitos decimais Bits expoentes Decimal E max Viés do expoente E min E max Notas
binário 16 Meia precisão 2 11 3,31 5 4,51 2 4 −1 = 15 -14 +15 não básico
binary32 Precisão simples 2 24 7,22 8 38,23 2 7 −1 = 127 -126 +127
binary64 Dupla precisão 2 53 15,95 11 307,95 2 10 −1 = 1023 -1022 +1023
binário 128 Precisão quádrupla 2 113 34,02 15 4931,77 2 14 −1 = 16383 -16382 +16383
binário256 Precisão do octuplo 2 237 71,34 19 78913,2 2 18 −1 = 262143 -262142 +262143 não básico
decimal32 10 7 7 7,58 96 101 -95 +96 não básico
decimal64 10 16 16 9,58 384 398 -383 +384
decimal 128 10 34 34 13,58 6144 6176 -6143 +6144

Observe que na tabela acima, os expoentes mínimos listados são para números normais; a representação de número subnormal especial permite que números ainda menores sejam representados (com alguma perda de precisão). Por exemplo, o menor número positivo que pode ser representado em binary64 é 2 −1074 ; as contribuições para a figura −1074 incluem o valor E min −1022 e todos, exceto um dos 53 bits de significando (2 −1022 - (53 - 1)  = 2 −1074 ).

Os dígitos decimais são dígitos × log 10 base . Isso dá uma precisão aproximada no número de dígitos decimais.

E max decimal é Emax × log 10 base . Isso dá um valor aproximado do expoente decimal máximo.

Os formatos binary32 (único) e binary64 (duplo) são dois dos formatos mais comuns usados ​​hoje. A figura abaixo mostra a precisão absoluta para ambos os formatos em uma faixa de valores. Esta figura pode ser usada para selecionar um formato apropriado, dado o valor esperado de um número e a precisão necessária.

Precisão de binary32 e binary64 na faixa de 10 -12 a 10 12


Um exemplo de layout para ponto flutuante de 32 bits é

Float example.svg

e o layout de 64 bits é semelhante .

Formatos de precisão estendidos e extensíveis

O padrão especifica formatos opcionais de precisão estendidos e extensíveis, que fornecem maior precisão do que os formatos básicos. Um formato de precisão estendido estende um formato básico, usando mais precisão e mais intervalo de expoentes. Um formato de precisão extensível permite ao usuário especificar a precisão e o intervalo de expoentes. Uma implementação pode usar qualquer representação interna que escolher para tais formatos; tudo o que precisa ser definido são seus parâmetros ( b , p e emax ). Esses parâmetros descrevem exclusivamente o conjunto de números finitos (combinações de sinal, significando e expoente para a raiz fornecida) que ele pode representar.

O padrão recomenda que os padrões de linguagem fornecer um método de especificação p e Emax para cada base suportada b . O padrão recomenda que os padrões e implementações de linguagem suportem um formato estendido que tem uma precisão maior do que o maior formato básico suportado para cada raiz b . Para um formato estendido com uma precisão entre dois formatos básicos, o intervalo do expoente deve ser tão grande quanto o do próximo formato básico mais amplo. Portanto, por exemplo, um número binário de precisão estendida de 64 bits deve ter um 'emax' de pelo menos 16383. O formato estendido x87 de 80 bits atende a esse requisito.

Formatos de intercâmbio

Os formatos de intercâmbio são destinados à troca de dados de ponto flutuante usando uma sequência de bits de comprimento fixo para um determinado formato.

Binário

Para a troca de números de ponto flutuante binários, são definidos formatos de intercâmbio de comprimento 16 bits, 32 bits, 64 bits e qualquer múltiplo de 32 bits ≥ 128. O formato de 16 bits destina-se à troca ou armazenamento de pequenos números (por exemplo, para gráficos).

O esquema de codificação para esses formatos de intercâmbio binário é o mesmo do IEEE 754-1985: um bit de sinal, seguido por w bits expoentes que descrevem o deslocamento do expoente por uma polarização e p  - 1 bits que descrevem o significando. A largura do campo expoente para um formato de k bits é calculada como w  = round (4 log 2 ( k )) - 13. Os formatos de 64 e 128 bits existentes seguem esta regra, mas os formatos de 16 e 32 bits formatos têm mais bits expoentes (5 e 8 respectivamente) do que esta fórmula forneceria (3 e 7 respectivamente).

Tal como acontece com IEEE 754-1985, o campo expoente tendencioso é preenchido com todos os 1 bits para indicar o infinito (campo de significando à direita = 0) ou um NaN (campo de significando à direita ≠ 0). Para NaNs, NaNs silenciosos e NaNs de sinalização são diferenciados pelo uso do bit mais significativo do campo de significando à direita exclusivamente, e a carga útil é transportada nos bits restantes.

Decimal

Para a troca de números de ponto flutuante decimal, são definidos formatos de intercâmbio de qualquer múltiplo de 32 bits. Tal como acontece com o intercâmbio binário, o esquema de codificação para os formatos de intercâmbio decimal codifica o sinal, o expoente e o significando. Duas codificações de nível de bit diferentes são definidas e o intercâmbio é complicado pelo fato de que algum indicador externo da codificação em uso pode ser necessário.

As duas opções permitem que o significando seja codificado como uma sequência compactada de dígitos decimais usando decimal densamente compactado ou, alternativamente, como um inteiro binário . O primeiro é mais conveniente para implementação direta de hardware do padrão, enquanto o último é mais adequado para emulação de software em um computador binário. Em ambos os casos, o conjunto de números (combinações de sinal, significando e expoente) que podem ser codificados é idêntico, e os valores especiais (± zero com o expoente mínimo, ± infinito, NaNs silenciosos e NaNs de sinalização) têm codificações idênticas.

Regras de arredondamento

O padrão define cinco regras de arredondamento. As duas primeiras regras são arredondadas para um valor mais próximo; os outros são chamados de arredondamentos direcionados :

Arredondamentos para o mais próximo

  • Arredonda para o mais próximo, empata para pares  - arredonda para o valor mais próximo; se o número cair no meio, ele é arredondado para o valor mais próximo com um dígito ainda menos significativo; este é o padrão para ponto flutuante binário e o padrão recomendado para decimal.
  • Arredondar para o mais próximo, empata a partir de zero  - arredonda para o valor mais próximo; se o número cair no meio, é arredondado para o valor mais próximo acima (para números positivos) ou abaixo (para números negativos); isso é uma opção para o ponto flutuante decimal.

Arredondamentos direcionados

  • Arredondar para 0  - arredondamento direcionado para zero (também conhecido como truncamento ).
  • Arredondar para + ∞  - arredondamento direcionado para o infinito positivo (também conhecido como arredondamento para cima ou teto ).
  • Arredondar para −∞  - arredondamento direcionado para o infinito negativo (também conhecido como arredondamento para baixo ou piso ).
Exemplo de arredondamento para inteiros usando as regras IEEE 754
Modo Valor de exemplo
+11,5 +12,5 -11,5 -12,5
para mais próximo, laços com mesmo +12,0 +12,0 -12,0 -12,0
para o mais próximo, empata longe do zero +12,0 +13,0 -12,0 -13,0
em direção a 0 +11,0 +12,0 -11,0 -12,0
em direção a + ∞ +12,0 +13,0 -11,0 -12,0
em direção a −∞ +11,0 +12,0 -12,0 -13,0

A menos que especificado de outra forma, o resultado de ponto flutuante de uma operação é determinado pela aplicação da função de arredondamento no resultado infinitamente preciso (matemático). Tal operação é considerada corretamente arredondada . Esse requisito é chamado de arredondamento correto .

Operações necessárias

As operações necessárias para um formato aritmético compatível (incluindo os formatos básicos) incluem:

  • Operações aritméticas (somar, subtrair, multiplicar, dividir, raiz quadrada, multiplicação fundida-somar , resto)
  • Conversões (entre formatos, de e para strings, etc. )
  • Escalonamento e (para decimal) quantização
  • Copiar e manipular o sinal (abs, negar, etc. )
  • Comparações e ordenação total
  • Classificação e teste para NaNs, etc.
  • Teste e configuração de sinalizadores
  • Operações diversas.

Predicados de comparação

O padrão fornece predicados de comparação para comparar um dado de ponto flutuante com outro no formato aritmético suportado. Qualquer comparação com um NaN é tratada como não ordenada. −0 e +0 comparam como iguais.

Predicado de ordenação total

O padrão fornece um predicado totalOrder , que define uma ordenação total dos membros canônicos do formato aritmético suportado. O predicado concorda com os predicados de comparação quando um número de ponto flutuante é menor que o outro. O predicado totalOrder não impõe uma ordem total em todas as codificações em um formato. Em particular, ele não distingue entre diferentes codificações da mesma representação de ponto flutuante, como quando uma ou ambas as codificações são não canônicas. IEEE 754-2019 incorpora esclarecimentos sobre totalOrder .

Para os formatos de intercâmbio binário cuja codificação segue a recomendação IEEE 754-2008 sobre a colocação do bit de sinalização NaN , a comparação é idêntica àquela que muda os números de ponto flutuante para um número inteiro de sinal-magnitude (assumindo uma ordenação de carga consistente com esta comparação), um velho truque para comparação de FP sem FPU.

Manipulação de exceção

O padrão define cinco exceções, cada uma das quais retorna um valor padrão e tem um sinalizador de status correspondente que é gerado quando a exceção ocorre. Nenhum outro tratamento de exceção é necessário, mas alternativas não padrão adicionais são recomendadas (consulte § Tratamento de exceção alternativo ).

As cinco exceções possíveis são:

  • Operação inválida: matematicamente indefinida, por exemplo , a raiz quadrada de um número negativo. Por padrão, retorna qNaN.
  • Divisão por zero: uma operação em operandos finitos fornece um resultado infinito exato, por exemplo , 1/0 ou log (0). Por padrão, retorna ± infinito.
  • Overflow: um resultado finito é muito grande para ser representado com precisão ( ou seja , seu expoente com uma faixa de expoente ilimitada seria maior do que emax ). Por padrão, retorna ± infinito para os modos de arredondamento para o mais próximo (e segue as regras de arredondamento para os modos de arredondamento direcionados).
  • Underflow: um resultado é muito pequeno (fora da faixa normal). Por padrão, retorna um número menor ou igual ao número normal positivo mínimo em magnitude (seguindo as regras de arredondamento); um subnormal sempre implica uma exceção de underflow, mas por padrão, se for exato, nenhum sinalizador é gerado.
  • Inexato: o resultado exato ( isto é , não arredondado) não é representável com exatidão. Por padrão, retorna o resultado arredondado corretamente.

Essas são as mesmas cinco exceções definidas no IEEE 754-1985, mas a exceção de divisão por zero foi estendida a outras operações além da divisão.

Algumas implementações de ponto flutuante decimal definem exceções adicionais, que não fazem parte do IEEE 754:

  • Preso: o expoente de um resultado é muito grande para o formato de destino. Por padrão, zeros finais serão adicionados ao coeficiente para reduzir o expoente ao maior valor utilizável. Se isso não for possível (porque isso faria com que o número de dígitos necessários fosse maior do que o formato de destino), ocorrerá uma exceção de estouro.
  • Arredondado: o coeficiente de um resultado requer mais dígitos do que o fornecido pelo formato de destino. Uma exceção inexata é sinalizada se qualquer dígito diferente de zero for descartado.

Além disso, operações como quantizar quando um dos operandos é infinito ou quando o resultado não se ajusta ao formato de destino, também sinalizarão uma exceção de operação inválida.

Recomendações

Tratamento de exceção alternativo

O padrão recomenda o tratamento de exceção opcional em várias formas, incluindo a pré-substituição de valores padrão definidos pelo usuário e armadilhas (exceções que alteram o fluxo de controle de alguma forma) e outros modelos de tratamento de exceção que interrompem o fluxo, como try / catch. As armadilhas e outros mecanismos de exceção permanecem opcionais, como eram no IEEE 754-1985.

Operações recomendadas

A cláusula 9 do padrão recomenda operações matemáticas adicionais que os padrões de linguagem devem definir. Nenhum é necessário para estar em conformidade com o padrão.

Operações aritméticas recomendadas, que devem ser arredondadas corretamente:

As funções asinPi , acosPi e tanPi não faziam parte do padrão IEEE 754-2008 porque foram consideradas menos necessárias. asinPi , acosPi foram mencionados, mas isso foi considerado um erro. Todos os três foram adicionados na revisão de 2019.

As operações recomendadas também incluem configurar e acessar a direção de arredondamento do modo dinâmico e operações de redução de vetor definidas pela implementação, como soma, produto escalado e produto escalar , cuja precisão não é especificada pelo padrão.

A partir de 2019, as operações aritméticas aumentadas para os formatos binários também são recomendadas. Essas operações, especificadas para adição, subtração e multiplicação, produzem um par de valores consistindo em um resultado arredondado corretamente para o mais próximo no formato e o termo de erro, que é representável exatamente no formato. No momento da publicação do padrão, nenhuma implementação de hardware é conhecida, mas operações muito semelhantes já foram implementadas no software usando algoritmos bem conhecidos. A história e a motivação para sua padronização são explicadas em um documento de referência.

A partir de 2019, os anteriormente exigidos minNum, maxNum, minNumMag e maxNumMag no IEEE 754-2008 agora são excluídos devido à sua não associatividade. Em vez disso, dois conjuntos de novas operações mínimo e máximo são recomendados. O primeiro conjunto contém minimum, minimumNumber, maximum e maximumNumber . O segundo conjunto contém minimumMagnitude, minimumMagnitudeNumber, maximumMagnitude e maximumMagnitudeNumber . A história e a motivação para essa mudança são explicadas em um documento de histórico.

Avaliação de expressão

O padrão recomenda como os padrões de linguagem devem especificar a semântica das sequências de operações e aponta as sutilezas dos significados literais e otimizações que alteram o valor de um resultado. Em contraste, a versão anterior de 1985 do padrão deixava aspectos da interface da linguagem não especificados, o que levava a um comportamento inconsistente entre compiladores ou diferentes níveis de otimização em um compilador de otimização .

As linguagens de programação devem permitir que um usuário especifique uma precisão mínima para cálculos intermediários de expressões para cada raiz. Isso é referido como largura preferencial no padrão e deve ser possível defini-la por bloco. Cálculos intermediários dentro de expressões devem ser calculados, e quaisquer temporários salvos, usando o máximo da largura dos operandos e a largura preferida se configurada. Assim, por exemplo, um compilador visando hardware de ponto flutuante x87 deve ter um meio de especificar que os cálculos intermediários devem usar o formato de extensão dupla . O valor armazenado de uma variável deve sempre ser usado ao avaliar expressões subsequentes, ao invés de qualquer precursor antes do arredondamento e atribuição à variável.

Reprodutibilidade

A versão IEEE 754-1985 do padrão permitiu muitas variações nas implementações (como a codificação de alguns valores e a detecção de certas exceções). O IEEE 754-2008 reduziu essas permissões, mas algumas variações ainda permanecem (especialmente para formatos binários). A cláusula de reprodutibilidade recomenda que os padrões de linguagem forneçam um meio de escrever programas reproduzíveis (ou seja, programas que produzirão o mesmo resultado em todas as implementações de uma linguagem) e descreve o que precisa ser feito para obter resultados reproduzíveis.

Representação de personagem

O padrão requer operações de conversão entre formatos básicos e formatos de sequência de caracteres externos . As conversões de e para um formato de caractere decimal são necessárias para todos os formatos. A conversão para uma sequência de caracteres externa deve ser tal que a conversão de volta usando o arredondamento para o mais próximo, empates para o par irá recuperar o número original. Não há necessidade de preservar a carga útil de um NaN silencioso ou NaN de sinalização, e a conversão da sequência de caracteres externa pode transformar um NaN de sinalização em NaN silencioso.

O valor binário original será preservado convertendo para decimal e vice-versa usando:

  • 5 dígitos decimais para o binário 16,
  • 9 dígitos decimais para binário 32,
  • 17 dígitos decimais para binary64,
  • 36 dígitos decimais para binary128.

Para outros formatos binários, o número necessário de dígitos decimais é

onde p é o número de bits significativos no formato binário, por exemplo, 237 bits para binary256.

Ao usar um formato de ponto flutuante decimal, a representação decimal será preservada usando:

  • 7 dígitos decimais para decimal 32,
  • 16 dígitos decimais para decimal 64,
  • 34 dígitos decimais para decimal128.

Algoritmos, com código, para conversão corretamente arredondada de binário para decimal e decimal para binário são discutidos por Gay, e para teste - por Paxson e Kahan.

Veja também

Notas

Referências

Padrões

Referências secundárias

Leitura adicional

links externos