2011-08-06 18 views
7

Estoy tratando de convertir un número de coma flotante de precisión extendida de 80 bits (en un buffer) en el doble. El buffer contiene básicamente el contenido de un registro x87.Números de coma flotante y subnormales de 80 bits

This question me ayudó a empezar porque no estaba tan familiarizado con el estándar IEEE. De todos modos, estoy luchando para encontrar información útil sobre números subnormales (o desnormalizados) en el formato de 80 bits. Lo que sé es que a diferencia de float32 o float64 no tiene un bit oculto en la mantisa (no hay una adición implícita de 1.0), así que una forma de saber si un número está normalizado es comprobar si el bit más alto en la mantisa es conjunto. Eso me deja con la siguiente pregunta:

Por lo que wikipedia me dice, float32 y float64 indican un número subnormal con un exponente (sesgado) de 0 y una mantisa distinta de cero.

  • ¿Qué me dice eso en un flotador de 80 bits?
  • ¿Pueden los flotadores de 80 bits con mantisa < 1.0 incluso tener un exponente distinto de cero?
  • Alternativamente, ¿pueden los flotadores de 80 bits con un exponente de 0 incluso tener una mantisa> = 1.0?

EDIT: Creo que la cuestión se reduce a:

¿Puedo esperar que el FPU para desinfectar exponente y mantisa poco más alta en los registros x87?

En caso negativo, ¿qué tipo de número debería dar la conversión? ¿Debería ignorar el exponente por completo en ese caso? O es qNaN?

EDIT:

leí la sección FPU en el manual de Intel (Intel® 64 e IA-32 Arquitecturas de Software Manual del desarrollador, volumen 1: Arquitectura básica) que era menos miedo de lo que había temido . Pues resulta que los siguientes valores no están definidos:

  • exponente == 0 + mantisa con el bit más alto establecido
  • exponente = 0 + mantisa sin el conjunto de bits más alta

Doesn! Mencione si estos valores pueden aparecer en la naturaleza, ni si se convierten internamente. Por lo tanto, desempolvé Ollydbg y configuré bits manualmente en los registros x87. I hacen a mano ST (0) para contener todos los bits establecidos en el exponente y una mantisa de 0. Entonces lo hice ejecutar

FSTP QWORD [ESP] 
FLD QWORD [ESP] 

El valor almacenado en [ESP] se convirtió en una señalización NaN. Después del FLD, ST(0) contenía un NaN silencioso.

Supongo que eso responde mi pregunta. Acepté la solución J-16 SDiZ porque es la solución más directa (aunque no explica explícitamente algunos de los detalles más finos).

De todos modos, caso resuelto. Gracias a todos.

+0

¿No tiene a mano una unidad 8087 para hacer el trabajo? –

+0

Probablemente va a necesitar pedirle a alguien que conozca un ensamblador que lo vuelva a colocar en un colector asociado con una variable en particular. –

+0

@David Heffernan: Sí, pero C++ (de ahí la etiqueta) no garantiza que el doble largo tenga 80 bits de tamaño. De hecho, VC++ define long double y double para tener el mismo tamaño (64 bits). El ensamblador en línea parece ser la única forma de obtener conversiones perfectas (hay código en la pregunta que he vinculado), pero prefiero usar C++ sin formato, especialmente porque no hay un ensamblador en línea en VC++ de 64 bits. – pezcode

Respuesta

3

Trate SoftFloat biblioteca, que tiene floatx80_to_float32, floatx80_to_float64 y floatx80_to_float128. Detecta el formato nativo, actúa en consecuencia.

3

El problema con la búsqueda de información sobre números subnormales de 80 bits podría deberse a que el 8087 no utiliza ninguna desnormalización especial para ellos. Encontrado esto en la página MSDNs en Type float (C):

los valores listados en esta tabla sólo se aplican a normalizada números de coma flotante; los números de punto flotante desnormalizados tienen un valor mínimo más pequeño. Tenga en cuenta que los números retenidos en los registros 80x87 siempre se representan en forma normalizada de 80 bits; números solo pueden ser representados en forma no normalizada cuando se almacenan en 32 bits o 64 bits variables de coma flotante (variables de tipo flotante y tipo largo).

Editar

Lo anterior podría ser cierto para cómo Microsoft hace uso de la FPU registra. Encontrado otra fuente que indican esto:

FPU Data types:

El 80x87 FPU almacena generalmente valores en un formato normalizado. Cuando se normaliza un número de punto flotante , el H.O. el bit es siempre uno. En los formatos de punto flotante de 32 y 64 bits, el 80x87 no almacena en realidad este bit, el 80x87 siempre asume que es uno. Por lo tanto, 32 y los números de punto flotante de 64 bits siempre están normalizados. En el formato de coma flotante de precisión de 80 bit , el 80x87 no supone que el H.O. un poco de la mantisa es uno, el H.O. un poco del número aparece como parte de la cadena de bits.

Los valores normalizados proporcionan la mayor precisión para un número determinado de bits. Sin embargo, hay una gran cantidad de valores no normalizados que podemos representar con el formato de 80 bits. Estos valores son muy cercanos a cero y representan el conjunto de valores cuya mantisa H.O. el bit no es cero. Las FPU de 80x87 admiten una forma especial de 80 bits conocida como valores desnormalizados.

+2

Creo que la motivación original de la FPU de 80 bits fue que puede hacer operaciones de 64 bits con mayor precisión, pero siempre se espera que interactúe mediante flotadores de 64 bits. En ese escenario, nunca crearía flotadores denormales de 80 bits, porque incluso el flotador más pequeño de 64 bits sigue siendo un flotador normal de 80 bits. –

+0

@Kerrek SB: Eso no significa que sea imposible alimentarlo con dos flotadores de 64 bits, calcule un poco y obtenga un resultado que incluso los 80 bits no pueden mantener en forma normalizada. – pezcode

+0

@pezcode: claro, pero retroceder cualquier valor denormal de 80 bits será cero en la representación de 64 bits, por lo que no hay problema, solo subdesbordamiento. –

Cuestiones relacionadas