Qual é o primeiro número inteiro que um flutuador IEEE 754 é incapaz de representar exatamente?

162

Para maior clareza, se estou usando uma linguagem que implementa IEE 754 floats e declaro:

float f0 = 0.f;
float f1 = 1.f;

... e depois imprimi-los novamente, receberei 0,0000 e 1,0000 - exatamente.

Mas o IEEE 754 não é capaz de representar todos os números ao longo da linha real. Perto de zero, as 'lacunas' são pequenas; à medida que você se afasta, as lacunas aumentam.

Então, minha pergunta é: para um flutuador IEEE 754, que é o primeiro inteiro (mais próximo de zero) que não pode ser representado exatamente? Por enquanto, só estou realmente preocupado com flutuadores de 32 bits, embora eu esteja interessado em ouvir a resposta de 64 bits, se alguém der!

Eu pensei que isso seria tão simples quanto calcular 2 bits_de_mantissa e adicionar 1, onde bits_of_mantissa é quantos bits o padrão expõe. Eu fiz isso para carros alegóricos de 32 bits na minha máquina (MSVC ++, Win64), e parecia bom.

Floomi
fonte
Por que você adicionou um se queria um número irrepresentável? E que número você usou ou recebeu? E isso é lição de casa? E o título da sua pergunta diz "número inteiro", mas sua pergunta diz "flutuar".
RSU
5
Porque achei que maximizar a mantissa me daria o maior número representável. 2 ^ 22. Não, é uma questão de curiosidade. Eu sempre me senti culpado por colocar entradas em carros alegóricos, mesmo quando sei que o int em questão sempre será muito pequeno. Eu quero saber qual é o limite superior. Tanto quanto posso dizer, o título e a pergunta são os mesmos, apenas redigidos de maneira diferente.
Floomi
1
duplicado de stackoverflow.com/questions/1848700/… ?
FrankH.
1
@KyleStrand revertiu ^ 2. Não sei por que um parecia mais correto para mim do que o outro na época. Agora os dois parecer estranho em comparação com “... é o número de bits ...”
Pascal Cuoq

Respostas:

211

2 bits de mantissa + 1 + 1

O +1 no expoente (mantissa bits + 1) é porque, se a mantissa contém abcdef...o número que representa 1.abcdef... × 2^e, na verdade , fornecendo um bit implícito extra de precisão.

Portanto, o primeiro número inteiro que não pode ser representado com precisão e será arredondado é:
Para float, 16.777.217 (2 24 + 1).
Para double, 9.007.199.254.740.993 (2 53 + 1).

>>> 9007199254740993.0
9007199254740992
kennytm
fonte
Declarei a floate defini-o como 16.777.217. Mas quando imprimi cout, resultou em 16.777.216. Estou usando C++. Por que não consigo obter 16.777.217?
nitrato de sódio
18
@sodiumnitrate Verifique o título da pergunta. 16777217 é o primeiro número inteiro incapaz de ser representado exatamente.
Kennytm 15/10
Ok obrigado. Fiquei confuso, desculpe por isso. Porém, eu tenho outra pergunta: após 16777216, o próximo número inteiro representável não deve ser 2 * 16777216? Quando eu executar um programa semelhante, recebo 16777218 adicionando 2 a 16777126.
nitrato de sódio
5
O próximo número inteiro é realmente 16777218, porque 2 agora se torna o último dígito binário significativo.
Kennytm 16/10
6
Em C ++, é isso (1 << std::numeric_limits<float>::digits) + 1, e em C (1 << FLT_MANT_DIG) + 1,. O primeiro é bom porque pode fazer parte de um modelo. Não adicione o +1 se quiser apenas o maior número inteiro representável.
Henry Schreiner
38

O maior valor representável por um número inteiro de n bits é 2 n -1. Como observado acima, a floattem 24 bits de precisão no significado e parece implicar que 2 24 não se encaixaria.

No entanto .

Potências de 2 dentro do intervalo do expoente são exatamente representáveis ​​como 1,0 × 2 n , então 2 24 pode caber e, consequentemente, o primeiro número inteiro não representável floaté 2 24 +1. Como observado acima. Novamente.

assim falou ak
fonte
1
Isso explica claramente a parte "pouco implícita de precisão" da outra. Obrigado.
Chappjc