Refrescante en floating points (también PDF), IEEE-754 y tomando parte in this discussion on floating point rounding when converting to strings, me llevó a jugar: cómo puedo obtener el valor máximo y mínimo para un dado un número de punto flotante cuyas representaciones binarias son iguales.Encontrar min/max de un flotador/doble que tiene la misma representación interna
Descargo de responsabilidad: para esta discusión, me gusta adherirme al punto flotante de 32 y 64 bits como lo describe IEEE-754. No estoy interesado en el punto flotante extendido (80 bits) o quads (IEEE-754-2008 de 128 bits) ni en ningún otro estándar (IEEE-854).
Antecedentes: Las computadoras son malas para representar 0.1
en representación binaria. En C#, un flotante representa esto como 3DCCCCCD
internamente (C# usa redondeada a más cercana) y un doble como 3FB999999999999A
. Los mismos patrones de bits se utilizan para 0.100000005
decimal (flotante) y 0.1000000000000000124
(doble), pero no para 0.1000000000000000144
(doble).
Por conveniencia, el siguiente código C# da estas representaciones internas:
string GetHex(float f)
{
return BitConverter.ToUInt32(BitConverter.GetBytes(f), 0).ToString("X");
}
string GetHex(double d)
{
return BitConverter.ToUInt64(BitConverter.GetBytes(d), 0).ToString("X");
}
// float
Console.WriteLine(GetHex(0.1F));
// double
Console.WriteLine(GetHex(0.1));
En el caso de 0.1
, no hay menor número decimal que se representa con el mismo patrón de bits, cualquier 0.99...99
dará lugar a una diferente la representación de bit (es decir, float para 0.999999937
produce 3F7FFFFF
internamente).
Mi pregunta es simple: cómo puedo encontrar el valor decimal más bajo y más alto para un flotante determinado (o doble) que se almacena internamente en la misma representación binaria.
Por qué: (Sé que preguntará) para encontrar el error al redondear en .NET cuando se convierte en una cadena y cuando se convierte a partir de una cadena, para encontrar el valor exacto interno y para entender el mío redondeando errores mejor.
Supongo que es algo como: tomar la mantisa, eliminar el resto, obtener su valor exacto, obtener uno (mantissa-bit) más alto y calcular la media: cualquier valor inferior a ese arrojará el mismo patrón de bits. Mi problema principal es: cómo obtener la parte fraccionaria como un entero (la manipulación de bits no es mi activo más fuerte). Jon Skeet's DoubleConverter clase puede ser útil.
Excelente respuesta, parece que la información que estaba buscando. Trataré de resolverlo en C# y volver aquí si necesito más ayuda con las cositas. Me di cuenta de que has trabajado con el equipo IEEE-754 para construir el estándar. Me siento honrado :). ¡Y tienes razón en ese error tipográfico! Estaba tan sorprendido que no pude encontrar un valor menor, pero lo di por hecho y lo anoté, errores y todo, ¡jaja! – Abel