Qual é o maior número inteiro "não flutuante" que pode ser armazenado em um tipo duplo IEEE 754 sem perder a precisão?
Qual é o maior número inteiro "não flutuante" que pode ser armazenado em um tipo duplo IEEE 754 sem perder a precisão?
Respostas:
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_MAX
ou 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 :
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.
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
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
que produz o mesmo resultado
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.
while (dbl + 1 != dbl) dbl++;
que dbl + 1 != dbl
pode avaliar o uso da long double
matemática - considere FLT_EVAL_METHOD == 2
. Isso pode terminar em um loop infinito.
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.
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:
0x7FE
(2046, que representa 1023 após o viés é subtraído), e não 0x7FF
(2047, que indica a NaN
ou infinito).0xFFFFFFFFFFFFF
que é 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 .
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.
Qual é o valor da expressão?
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
de <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_RADIX
e DBL_MANT_DIG
, mas não tenho certeza se confiaria totalmente no resultado.
double
corresponde 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.