En .NET a float
se representa utilizando un número flotante de precisión simple IEEE binary32 almacenado utilizando 32 bits. Aparentemente el código construye este número ensamblando los bits en un int
y luego lo lanza a un float
usando unsafe
. El elenco es lo que en términos de C++ se llama reinterpret_cast
donde no se realiza ninguna conversión cuando se realiza el reparto; los bits simplemente se reinterpretan como un nuevo tipo.

El número ensamblado es 4019999A
en hexadecimal o 01000000 00011001 10011001 10011010
en binario:
- El bit de signo es 0 (es un número positivo).
- Los bits de exponente son
10000000
(o 128) que dan como resultado el exponente 128 - 127 = 1 (la fracción se multiplica por 2^1 = 2).
- Los bits de fracción son
00110011001100110011010
que, como mínimo, casi tienen un patrón reconocible de ceros y unos.
volvió El flotador tiene los mismos bits exactas como 2,4 convertidos a punto flotante y toda la función simplemente se pueden sustituir por el literal 2.4f
.
El cero final que tipo de "rompe el patrón de bits" de la fracción ¿existe quizás para hacer que el flotante coincida con algo que se puede escribir usando un literal de punto flotante?
Entonces, ¿cuál es la diferencia entre un reparto regular y esto rara "fundido insegura"?
asumir el siguiente código:
int result = 0x4019999A // 1075419546
float normalCast = (float) result;
float unsafeCast = *(float*) &result; // Only possible in an unsafe context
La primera fundido lleva el número entero 1075419546
y la convierte a su representación de punto flotante, por ejemplo, 1075419546f
. Esto implica calcular los bits de signo, exponente y fracción necesarios para representar el número entero original como un número de coma flotante. Este es un cálculo no trivial que debe hacerse.
El segundo lanzamiento es más siniestro (y solo se puede realizar en un contexto inseguro). El &result
toma la dirección de result
devolviendo un puntero a la ubicación donde se almacena el número entero 1075419546
.El operador de desreferenciación del puntero *
se puede usar para recuperar el valor apuntado por el puntero. El uso de *&result
recuperará el entero almacenado en la ubicación; sin embargo, primero colocando el puntero en float*
(un puntero a float
), se recupera un flotador de la ubicación de la memoria, lo que da como resultado 2.4f
que está asignado al unsafeCast
. Entonces la narrativa de *(float*) &result
es dame un puntero a result
y asumo que el puntero apunta a float
y recupera el valor apuntado por el puntero.
A diferencia del primer elenco, el segundo elenco no requiere ningún cálculo. Simplemente empuja los 32 bits almacenados en result
en unsafeCast
(que afortunadamente también es de 32 bits).
En general, realizar un lanzamiento como este puede fallar de muchas maneras pero al usar unsafe
le está diciendo al compilador que usted sabe lo que está haciendo.
Dónde encontraste la muestra? ¿No tenía ninguna explicación sobre lo que se supone que debe devolver? –
está mal ..'result' no es un puntero ... no puedo convertir su dirección en un puntero flotante supongo – Anirudha
El código de muestra se utiliza con el ILSpy en el mscorlib/System/BitConvert/ToSingle. No se dio ninguna explicación. Necesito entender cuál es el flujo porque necesito convertirlo a PHP. – gchimuel