¿Cuál es el primer entero que un flotador IEEE 754 es incapaz de representar exactamente?

162

Para mayor claridad, si estoy usando un lenguaje que implementa flotadores IEE 754 y declaro:

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

... y luego imprimirlos de nuevo, obtendré 0.0000 y 1.0000, exactamente.

Pero IEEE 754 no es capaz de representar todos los números a lo largo de la línea real. Cerca de cero, las 'brechas' son pequeñas; A medida que te alejas, las brechas se hacen más grandes.

Entonces, mi pregunta es: para un flotante IEEE 754, ¿cuál es el primer entero (más cercano a cero) que no puede representarse exactamente? Solo estoy realmente preocupado por los flotantes de 32 bits por ahora, aunque me interesaría escuchar la respuesta de 64 bits si alguien me lo da.

Pensé que esto sería tan simple como calcular 2 bits_de_mantissa y agregar 1, donde bits_de_mantissa es cuántos bits expone el estándar. Hice esto para flotantes de 32 bits en mi máquina (MSVC ++, Win64), y parecía estar bien, sin embargo.

Floomi
fuente
¿Por qué agregaste uno si querías un número irrepresentable? ¿Y qué número usaste o obtuviste? ¿Y es esta tarea? Y el título de su pregunta dice "entero", pero su pregunta dice "flotante".
msw
55
Porque pensé que maximizar la mantisa me daría el número más alto representable. 2 ^ 22. No, es una pregunta de curiosidad. Siempre me he sentido culpable al poner ints en carrozas, incluso cuando sé que el int en cuestión siempre será muy pequeño. Quiero saber cuál es el límite superior. Por lo que puedo decir, el título y la pregunta son los mismos, pero expresados ​​de manera diferente.
Floomi
1
duplicado de stackoverflow.com/questions/1848700/… ?
FrankH.
1
@KyleStrand revertido ^ 2. No sé por qué una me parecía más correcta que la otra en ese momento. Ahora ambos parecen incómodos en comparación con "... es el número de bits ..."
Pascal Cuoq

Respuestas:

211

2 bits de mantisa + 1 + 1

El +1 en el exponente (mantissa bits + 1) se debe a que, si la mantisa contiene abcdef...el número que representa 1.abcdef... × 2^e, en realidad proporciona un bit de precisión adicional implícito.

Por lo tanto, el primer entero que no se puede representar con precisión y se redondeará es:
For float, 16,777,217 (2 24 + 1).
Para double, 9,007,199,254,740,993 (2 53 + 1).

>>> 9007199254740993.0
9007199254740992
kennytm
fuente
Declaré a floaty lo puse igual a 16.777.217. Pero cuando lo imprimí usando cout, resultó en 16,777,216. Estoy usando C++. ¿Por qué no puedo obtener 16,777,217?
nitrato de sodio
18
@ nitrato de sodio Verifique el título de la pregunta. 16777217 es el primer número entero incapaz de ser representado exactamente.
kennytm
OK gracias. Me confundí, lo siento por eso. Sin embargo, tengo otra pregunta: después de 16777216, ¿no debería ser el siguiente número entero representable 2 * 16777216? Cuando ejecuto un programa similar, obtengo 16777218 agregando 2 a 16777126.
nitrato de sodio
55
El siguiente entero es de hecho 16777218, porque 2 ahora se convierte en el último dígito binario significativo.
kennytm
66
En C ++, eso es (1 << std::numeric_limits<float>::digits) + 1, y en C (1 << FLT_MANT_DIG) + 1,. Lo primero es bueno porque puede ser parte de una plantilla. No agregue el +1 si solo desea el número entero representable más grande.
Henry Schreiner
38

El valor más grande representable por un entero de n bits es 2 n -1. Como se señaló anteriormente, a floattiene 24 bits de precisión en el significado que parece implicar que 2 24 no encajaría.

Sin embargo .

Las potencias de 2 dentro del rango del exponente son exactamente representables como 1.0 × 2 n , por lo que 2 24 puede caber y, en consecuencia, el primer entero no representable para float2 24 +1. Como se señaló anteriormente. De nuevo.

así habló AK
fuente
1
Esto explicaba claramente la parte de "precisión adicional implícita" de la otra. Gracias.
chappjc