Pregunta

I tienen un valor entero largo sin signo que representa un flotador utilizando el formato IEEE-754. ¿Cuál es la forma más rápida de imprimirlo como un flotador en C ++?

Yo sé una manera, pero estoy preguntando si hay una utilidad práctica en C ++ que sería mejor.

Ejemplo de la manera que sé es:

union
{
    unsigned long ul;
    float f;
} u;

u.ul = 1084227584; // in HEX, this is 0x40A00000

cout << "float value is: " << u.f << endl;

(Esto muestra "valor flotante es: 5")

¿Fue útil?

Solución

El método de unión que usted sugiere es la ruta habitual que la mayoría de la gente se tome. Sin embargo, es técnicamente comportamiento indefinido en C / C ++ para leer un miembro diferente de una unión de la que fue escrito más recientemente. A pesar de esto, sin embargo, está bien soportado entre más o menos todo compiladores.

Los punteros de fundición, como Jon skeet sugirió , es una mala idea - que viole la normas estrictas aliasing de C. Un compilador de optimización agresiva producirán un código incorrecto para esto, ya que se supone que los punteros de tipos unsigned long * y float * nunca alias entre sí.

La forma más correcta, en términos de cumplimiento de normas (es decir, no invocando un comportamiento indefinido), es para echar a través de un char*, ya que las reglas de alias estricto permiten un puntero char* poner un alias para un puntero de cualquier otro tipo:

unsigned long ul = 0x40A00000;
float f;
char *pul = (char *)&ul;  // ok, char* can alias any type
char *pf = (char *)&f;    // ok, char* can alias any type
memcpy(pf, pul, sizeof(float));

Aunque sinceramente, me gustaría ir con el método de unión. Desde el enlace cellperformance.com arriba:

  

Es un lenguaje muy común y está bien soportado por todos los principales compiladores. Como cuestión práctica, la lectura y la escritura a cualquier miembro de un sindicato, en cualquier orden, es una práctica aceptable.

Otros consejos

Es sólo funcionará en máquinas de 32 bits o máquinas donde sizeof (long) == sizeof (float). En las máquinas modernas es posible que desee utilizar int en lugar ... y que realmente hay que tener cuidado si usted está realizando este truco.

Yo estaba pensando lo mismo que Jon Skeet, pero él se me adelantó. Sin embargo, me gustaría hacer un poco más concisa que él.

cout << "float value is: " << *((float *) &ulValue)) << endl;

Se obtiene un puntero a su largo sin signo, a continuación, que reinterpretar como un puntero a flotar, a continuación, el puntero eliminación de referencias a flotar produce el valor flotante.

Desde que está haciendo esto en C ++, es más claro usar reinterpret_cast lugar de la antigua conversión de estilo C.

cout << "float value is: " << *(reinterpret_cast<float *>(&ulValue)) << endl;

EDIT: yo pensaba que esto era "espantosa", pero resulta ser peor de lo que pensaba - ver los comentarios para obtener más detalles. No recomendaría este enfoque, pero me voy de aquí para documentar la posibilidad (y la advertencia!)


Puede utilizar punteros:

long ul = 1084227584;
float* fp = (float*) &ul;
float f = *fp;

(Esto se puede condensar en una sola línea, pero creo que es más claro que no.)

Básicamente lo mismo que su sindicato ... e igualmente poco fiables a menos que esté seguro de los tamaños de los tipos involucrados.

Si la plataforma es compatible con ellos, que es mejor usar los nombres de los tipos de tamaño específico tanto para la parte entera y los tipos de punto flotante.

swegi tenía la dirección correcta, pero se perdió un carácter. La forma correcta es

long l = 1084227584L
float f = reinterpret_cast<float&>(l);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top