2009-05-05 9 views
6

Qual è il modo migliore di convertire un array di caratteri non firmati in un array float in C++?Lancio di una serie di caratteri non firmati in una matrice di float

ho attualmente hanno un ciclo for come segue

for (i=0 ;i< len; i++) 
    float_buff[i]= (float) char_buff[i]; 

Inoltre devo invertire la procedura, cioè convertire da char unsigned float (galleggiante conversione 8bit)

for (i=0 ;i< len; i++) 
    char_buff[i]= (unsigned char) float_buff[i]; 

Ogni consiglio essere apprezzato

Grazie

+1

Cosa stai facendo che richiede questo? –

risposta

2

La soluzione sembra a destra, anche se sulla via del ritorno, potresti perdere le cifre fluttuanti nel casting.

+0

Grazie Sono confuso su quale cast di stile C++ usare (reinterpretare o statico), quindi ho usato solo il vecchio stile, Qualsiasi idea. Inoltre, cosa succede quando si converte da float in unsigned char se float è maggiore di 255.0. (non preoccupato per le cifre dopo il punto) Grazie –

+0

Nel caso in cui il float è più grande di 255, avrà il risultato MOD dopo il cast (come con qualsiasi altro overflow). Ad esempio: float = 500 -> char = 254. float = 256 -> char = 0. BTW, ecco alcune informazioni su static_cast: http://stackoverflow.com/questions/103512/in-c-why-use-staticcastintx -instead-of-intx –

+0

Il comportamento se float è> = 256 non è definito - ottenere un valore di modulo potrebbe essere comune, ma non è garantito. –

2

Per quale scopo state facendo questo? Spingere un galleggiante in un char non ha molto senso. Sulla maggior parte delle piattaforme un float sarà di 4 byte e rappresenta un numero in virgola mobile, dove come un char sarà 1 byte e spesso rappresenta un singolo carattere. Perderai 3 byte di dati cercando di spingere un float in un carattere, giusto?

+0

Grazie Ho bisogno di convertire da float a 8 bit –

+0

Il cast eseguirà una conversione - troncando la parte frazionaria del float di distanza. Questo potrebbe essere esattamente ciò che la persona vuole. Una cosa fondamentale da tenere presente è che se la parte integrale del float non può essere rappresentata in un char senza segno (in genere se non è nell'intervallo 0-255) non è definita. –

+0

Grazie Michael, non mi dispiace perdere la parte frazionaria. Se il float è inferiore a 255, il cast funzionerà correttamente? Stavo per bloccare il risultato a 255 se il galleggiante fosse più grande di questo. Grazie –

8

La soluzione è più o meno l'opzione migliore, però, vorrei prendere in considerazione il passaggio a:

char_buff[i]= static_cast<unsigned char>(float_buff[i]); 
0

Se avete a che fare con le matrici molto grandi e le prestazioni è essenziale allora quanto segue può risultare leggermente più efficiente:

float *dst = float_buff; 
    unsigned char *src = char_buff; 

    for (i=0; i<len; i++) *dst++ = (float)*src++; 
+0

Grazie Dan, apprezzo il suggerimento –

+0

oppure std :: copy (char_buff, char_buff + len, float_buff); –

+0

L'utilizzo di std :: copy qui espone un difetto in STL (così come in C++). Quando fai una copia di qualcosa, dovrebbe essere vero che copia == originale. Facendo affidamento sul cast implicito, questo non è più vero, ed è per questo che il cast implicito dovrebbe essere evitato. –

2

Il tuo primo ciclo non richiede un lancio. È possibile convertire implicitamente da un tipo (ad es., unsigned char) a un tipo più ampio (ad es., float). Il tuo secondo ciclo dovrebbe usare static_cast:

for (i=0; i< len; i++) 
    char_buff[i]= static_cast<unsigned char>(float_buff[i]); 

Usiamo static_cast dire esplicitamente al compilatore di eseguire la conversione a un tipo più stretto. Se non si utilizza il cast, il compilatore potrebbe avvisare che la conversione potrebbe perdere dati. La presenza dell'operatore di cast significa che comprendi che potresti perdere la precisione dei dati e che tu stia bene. Questo è non un luogo appropriato per utilizzare reinterpret_cast. Con static_cast, hai almeno alcune restrizioni sulle conversioni che puoi eseguire (ad esempio, probabilmente non ti consente di convertire un Bird* in un Nuclear_Submarine*). reinterpret_cast non ha restrizioni di questo tipo.

Inoltre, ecco cosa ha da dire Bjarne Stroustrup su questo argomento.

9

Penso che il modo migliore è quello di utilizzare un oggetto funzione:

template <typename T> // T models Any 
struct static_cast_func 
{ 
    template <typename T1> // T1 models type statically convertible to T 
    T operator()(const T1& x) const { return static_cast<T>(x); } 
}; 

seguito da:

std::transform(char_buff, char_buff + len, float_buff, static_cast_func<float>()); 
std::transform(float_buff, float_buff + len, char_buff, static_cast_func<unsigned char>()); 

Questo è il più leggibile perché dice ciò che viene fatto in inglese: trasformare un sequenza in un altro tipo usando la fusione statica. E i cast futuri possono essere fatti in una sola riga.

1

Il cast è automatico, quindi non è necessario renderlo esplicito.
Ma è possibile utilizzare gli algoritmi standard:

std::copy(char_buff,char_buff+len,float_buff); 

riconversione da float a char v'è una potenziale perdita di informazioni. Quindi devi essere più esplicito.

std::transform(float_buff,float_buff+len,char_buff,MyTransform()); 

Qui si usa la MyTransform classe che dovrebbe avere un operatore() che prende un galleggiante e restituisce un char. Questo dovrebbe essere banale da implorare.

0

Nessuno ha menzionato questo, ma se stai facendo qualsiasi aritmetica con i float, potresti voler arrotondare invece di troncare ... se hai il char 49, e si trasforma in 4.9E1, dopo un po ' aritmetica, potrebbe trasformarsi in 4.89999999E1 che diventerà 48 quando lo trasformerai in un char.

Se non stai facendo nulla con il float, questo non dovrebbe essere un problema, ma allora perché ne hai bisogno come un galleggiante in primo luogo?

Problemi correlati