On. NET a float
viene rappresentato utilizzando un numero mobile a precisione singola IEEE binary32 memorizzato utilizzando 32 bit. Apparentemente il codice costruisce questo numero assemblando i bit in un int
e quindi lo proietta su un float
utilizzando unsafe
. Il cast è ciò che nei termini C++ è chiamato reinterpret_cast
dove non viene eseguita alcuna conversione quando viene eseguito il cast: i bit vengono semplicemente reinterpretati come un nuovo tipo.
Il numero assemblato è 4019999A
in esadecimale o 01000000 00011001 10011001 10011010
in binario:
- Il bit di segno è 0 (che è un numero positivo).
- I bit di esponente sono
10000000
(o 128) con conseguente esponente 128 - 127 = 1 (la frazione viene moltiplicata per 2^1 = 2).
- I bit di frazione sono
00110011001100110011010
che, se non altro, hanno quasi uno schema riconoscibile di zero e uno.
Il valore restituito ha gli stessi bit identici a 2.4 convertiti in virgola mobile e l'intera funzione può essere semplicemente sostituita dal valore letterale 2.4f
.
Lo zero finale che tipo di "interrompe il pattern di bit" della frazione è forse in grado di far corrispondere il float a qualcosa che può essere scritto utilizzando un letterale in virgola mobile?
Quindi qual è la differenza tra un cast normale e questo strano "cast non sicuro"?
assumere il codice seguente:
int result = 0x4019999A // 1075419546
float normalCast = (float) result;
float unsafeCast = *(float*) &result; // Only possible in an unsafe context
Il primo cast prende il numero intero 1075419546
e lo converte in sua rappresentazione in virgola mobile, ad esempio 1075419546f
. Ciò comporta il calcolo dei bit di segno, esponente e frazione richiesti per rappresentare il numero intero originale come un numero in virgola mobile. Questo è un calcolo non banale che deve essere fatto.
Il secondo cast è più sinistro (e può essere eseguito solo in un contesto non sicuro). Il &result
prende l'indirizzo di result
restituendo un puntatore alla posizione in cui è memorizzato il numero intero 1075419546
.L'operatore di dereferencing del puntatore *
può quindi essere utilizzato per recuperare il valore puntato dal puntatore. Tuttavia, utilizzando *&result
verrà recuperato il numero intero memorizzato nella posizione, convertendo prima il puntatore a float*
(un puntatore a float
) un oggetto mobile recuperato dalla posizione di memoria con conseguente assegnazione del numero 2.4f
mobile a unsafeCast
. Quindi la descrizione di *(float*) &result
è assegnami un puntatore a result
e supponiamo che il puntatore sia puntatore a float
e recuperi il valore puntato dal puntatore.
Contrariamente al primo cast, il secondo cast non richiede calcoli. Sposta semplicemente il 32 bit memorizzato in result
in unsafeCast
(che fortunatamente è anche a 32 bit).
In generale, un cast del genere può fallire in molti modi, ma usando unsafe
stai dicendo al compilatore che sai cosa stai facendo.
fonte
2012-10-04 08:09:14
dove hai trovato il campione? Non aveva alcuna spiegazione su cosa intendesse tornare? –
è errato ... il risultato non è un puntatore ... non posso convertire il suo indirizzo in virgola mobile, immagino – Anirudha
Trovo il codice di esempio usando ILSpy in mscorlib/System/BitConvert/ToSingle. Non è stata fornita alcuna spiegazione Devo capire qual è il flusso perché ho bisogno di convertirlo in PHP. – gchimuel