maior número inteiro que pode ser armazenado em um duplo

225

Qual é o maior número inteiro "não flutuante" que pode ser armazenado em um tipo duplo IEEE 754 sem perder a precisão?

Franck Freiburger
fonte

Respostas:

506

O maior / maior número inteiro que pode ser armazenado em um dobro sem perder a precisão é o mesmo que o maior valor possível de um dobro. Ou seja, DBL_MAXou aproximadamente 1,8 × 10 308 (se o seu dobro for um IEEE 754 de 64 bits). É um número inteiro. É representado exatamente. O que mais você quer?

Continue, pergunte-me qual é o maior número inteiro, para que ele e todos os números inteiros menores possam ser armazenados em duplicados IEEE de 64 bits sem perder a precisão. Um duplo IEEE de 64 bits possui 52 bits de mantissa, então acho que são 2 53 :

  • 2 53 + 1 não pode ser armazenado porque o 1 no início e o 1 no final têm muitos zeros no meio.
  • Qualquer coisa menor que 2 53 pode ser armazenada, com 52 bits explicitamente armazenados na mantissa e, em seguida, o expoente em vigor dando a você outro.
  • 2 53 obviamente pode ser armazenado, pois é um pequeno poder de 2.

Ou outra maneira de analisar: uma vez que o viés é retirado do expoente e ignorando o bit de sinal como irrelevante para a pergunta, o valor armazenado por um dobro é uma potência de 2, mais um número inteiro de 52 bits multiplicado por 2 expoente - 52 . Portanto, com o expoente 52, você pode armazenar todos os valores de 2 52 a 2 53  - 1. Em seguida, com o expoente 53, o próximo número que você pode armazenar após 2 53 é 2 53 + 1 × 2 53 - 52 . Portanto, a perda de precisão ocorre primeiro com 2 53 + 1.

Steve Jessop
fonte
126
+1 Bom trabalho ao perceber que a pergunta realmente não significava o que o solicitante provavelmente pretendia e fornecer as duas respostas ("tecnicamente correto" e "provavelmente esperado").
288 Pascal Cuoq
62
Ou "mexer" e "tentando ajudar" como eu tendem a chamá-los :-)
Steve Jessop
8
Eu me curvo para Tony, o Pônei, e nenhum outro.
Steve Jessop
11
Você não quer dizer "todos os números inteiros menores", mas todos os números inteiros de magnitude igual ou menor. Porque existem muitos números inteiros negativos abaixo de 2 ^ 53 e não podem ser representados exatamente em um duplo.
Southern Hospitality
13
Quero dizer menor, e é exatamente isso que quero dizer quando digo menor :-) -1.000.000 é menor que 1, mas não é menor.
Steve Jessop
77

9007199254740992 (ou seja, 9.007.199.254.740.992) sem garantias :)

Programa

#include <math.h>
#include <stdio.h>

int main(void) {
  double dbl = 0; /* I started with 9007199254000000, a little less than 2^53 */
  while (dbl + 1 != dbl) dbl++;
  printf("%.0f\n", dbl - 1);
  printf("%.0f\n", dbl);
  printf("%.0f\n", dbl + 1);
  return 0;
}

Resultado

9007199254740991
9007199254740992
9007199254740992
pmg
fonte
7
Supondo que seja "próximo", mas inferior a 2 ^ N, então um teste mais rápido é o double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);que produz o mesmo resultado
Seph
4
@Seph o que ...? Não? while (dbl == --dbl)irá repetir para sempre ou não. :) (neste caso, de modo algum, uma vez que é um 2 ^ N). Você terá que abordá-lo por baixo. De fato, também resultará em um a menos do que o esperado (uma vez que a verificação no loop while diminui dbl). E isso depende da ordem de execução, se o decréscimo for feito antes ou depois de avaliar o lado esquerdo (que é indefinido, tanto quanto eu sei). Se for o primeiro, sempre será verdade e ficará para sempre.
falstro
10
Talvez indique que 2 ^ 53 = 9.007.199.254.740.992 em algum lugar.
Xonatron
1
É difícil argumentar com isso! Bom experimento #
1155 MattM
Uma fraqueza no uso while (dbl + 1 != dbl) dbl++;que dbl + 1 != dblpode avaliar o uso da long doublematemática - considere FLT_EVAL_METHOD == 2. Isso pode terminar em um loop infinito.
chux - Restabelece Monica
25

A Wikipedia tem a dizer no mesmo contexto com um link para IEEE 754 :

Em um sistema de computador típico, um número de ponto flutuante binário de 'precisão dupla' (64 bits) possui um coeficiente de 53 bits (um dos quais está implícito), um expoente de 11 bits e um bit de sinal.

2 ^ 53 tem pouco mais de 9 * 10 ^ 15.

Carl Smotricz
fonte
@ Steve Jessop mais ou menos, é isso que estou dizendo. Eu também encontrei sistemas de hardware que não possuem uma FPU que ainda precisa ser compatível com IEEE, para que o "sistema típico" não me ajude realmente se eu voltar aqui 8 meses depois e precisar das mesmas informações para meu microcontrolador baseado em 68K (supondo que ele não tenha uma FPU ... não me lembro).
San Jacinto
14
@ San Jacinto - "Isso é inútil" é indevidamente duro. A resposta é bastante útil, apenas não tão útil como teria sido se incluísse o comentário de que sistemas de computador típicos realmente usam a re-representação IEEE 754.
23415 Stephen C. Steel
@ Stephen C. Steel, na verdade você está correto. No meu cenário, voltando a isso mais tarde e procurando o IEEE max, é impossivelmente ambíguo o que é um 'sistema típico', mas ainda há mérito na resposta além desta queixa.
San Jacinto
20

O maior número inteiro que pode ser representado no IEEE 754 duplo (64 bits) é o mesmo que o maior valor que o tipo pode representar, pois esse valor é ele próprio um número inteiro.

Isso é representado como 0x7FEFFFFFFFFFFFFF, que é composto de:

  • O sinal bit 0 (positivo) em vez de 1 (negativo)
  • O expoente máximo 0x7FE(2046, que representa 1023 após o viés é subtraído), e não 0x7FF(2047, que indica a NaNou infinito).
  • A mantissa máxima, 0xFFFFFFFFFFFFFque é de 52 bits, é 1.

Em binário, o valor é o 1 implícito seguido por outros 52 da mantissa, depois 971 zeros (1023 - 52 = 971) do expoente.

O valor decimal exato é:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

Isso é aproximadamente 1,8 x 10 308 .

Simon Biber
fonte
E o maior valor que ele pode representar com todos os valores entre ele e zero contíguo representável?
Aaron Franke
@AaronFranke A pergunta não perguntou sobre representação contígua, mas a resposta para essa pergunta diferente foi incluída na maioria das outras respostas aqui, ou mesmo erroneamente dada como resposta real. É 2⁵³ (2 à potência de 53).
Simon Biber
8

Você precisa olhar para o tamanho da mantissa. Um número de ponto flutuante IEEE 754 de 64 bits (que possui 52 bits, mais 1 implícito) pode representar exatamente números inteiros com um valor absoluto menor ou igual a 2 ^ 53.

Golfinho
fonte
8
Ele pode representar exatamente 2 ^ 53, também :-)
Steve Jessop
6

Qual é o valor da expressão?

http://en.wikipedia.org/wiki/Double_precision_floating-point_format

Jay
fonte
2
essa resposta seria muito melhor com uma citação.
San Jacinto
2
@ Carl bem, se o número inteiro tiver zeros além da esquerda, ele será armazenado com precisão.
Wilhelm
4
@all you downvoters: 1.7976931348623157 × 10 ^ 308 é um número inteiro exato. Vocês todos precisam assistir aulas de matemática corretivas ou algo assim?
D Moulding
6
Aqui estamos na semântica na discussão desta resposta irremediavelmente afundada. É verdade que esse número pode ser representado exatamente e, assim, cumpre a letra da pergunta. Mas todos sabemos que é uma pequena ilha de exatidão em um oceano de quase acidentes, e a maioria de nós interpolou corretamente a questão para significar "o maior número além do qual a precisão desce pelo ralo". Ah, não é maravilhoso que o CompSci seja uma ciência exata? :)
Carl Smotricz 4/09/09
2
@DanMoulding 1.7976931348623157 × 10 ^ 308 é um número inteiro exato, mas tenho certeza de que esse número inteiro específico não pode ser armazenado exatamente em um duplo.
Pascal Cuoq 26/09/14
2

DECIMAL_DIGde <float.h>deve dar pelo menos uma aproximação razoável do que isso. Como isso lida com dígitos decimais e é realmente armazenado em binário, você provavelmente pode armazenar algo um pouco maior sem perder a precisão, mas exatamente o quanto é difícil dizer. Suponho que você deve descobrir isso a partir de FLT_RADIXe DBL_MANT_DIG, mas não tenho certeza se confiaria totalmente no resultado.

Jerry Coffin
fonte
Isso não fornece uma resposta para a pergunta. Para criticar ou solicitar esclarecimentos a um autor, deixe um comentário abaixo da postagem.
31915 MichaelChirico
@ MichaelChirico: Isso responde à pergunta que ele pretendia fazer, como existia quando a resposta foi escrita. Para ver o histórico de edições da pergunta, clique no link "Jun 19 '14 editado às 11:40" na parte inferior da pergunta.
Jerry Coffin
sua resposta parece um comentário porque parece não ter a confiança / autoridade que uma resposta deveria ter ("deve fornecer pelo menos um razoável ..." "exatamente quanto ... é difícil dizer" "suponho ... "). Não tenho experiência na pergunta ou na resposta, por isso posso estar errado; apenas colocando meus dois centavos, já que fui enviado aqui da fila de revisão (o que eu acho que significa que outros usuários sinalizaram sua resposta).
22419 MichaelChirico
1
@ MichaelChirico: Eles podem ter - você está longe de ser o único que desconhece o assunto; o que o torna incomum é que você percebe que não o conhece. A maioria das respostas que parecem autoritativas sobre a precisão de um número de ponto flutuante em C é simplesmente equivocada. Por exemplo, muitos deles (a maioria) acima são baseados na falsa suposição de que a doublecorresponde diretamente a um tipo IEEE específico, mas isso não é necessário, e quando essa resposta foi escrita, a pergunta também não mencionou um tipo IEEE específico.
Jerry Coffin
Entendi. Talvez eu sugira adicionar essa informação à resposta.
MichaelChirico