Da float a String

Salve, come faccio a convertire un float in string? Grazie

atof http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

leo72:
atof
http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

Leo, non vuole l’ inverso?
Ho trovato questo:

char str[20]  = "";
float f = 4.5;
sprintf(str, "%f", f);

Ciao Uwe

Vero, vuole l'inverso. Sì, sprintf http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

è molto meglio la funzione dtostrf()

che vantaggi?

Io sto attualmente usando questo per inviare le temperature con webserver e funziona, poi non so cosa è migliore. Ti serve però una libreria

#include <floatToString.h>

float tempc1; // temperature variables
float tempc2; // temperature variables


char buffer1[25];
char buffer2[25];

String stA1 (floatToString(buffer1, tempc1, 1)); //converto float in string “,1 sta per n cifre dopo la virgola es: 23.7”
String stA2 (floatToString(buffer2, tempc2, 1)); //converto float in string

ciao

E dove trovi la libreria? Come lo fa la libreria internamente? Ciao Uwe

@lesto: il motivo lo leggi qui, che sicuramente è spiegato meglio di come farei io: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=96339&start=0

Comunque se compili un codice con sprintf() ti accorgi che occupa un casino di spazio, mentre con dtostrf() è sempre tanto ma è meno di sprintf.

Sprintf secondo me ha più senso usarla se oltre a convertire il numero vuoi inserire anche del testo nella stringa.

[quote author=Federico Vanzati link=topic=80601.msg609316#msg609316 date=1322553842] @lesto: il motivo lo leggi qui, che sicuramente è spiegato meglio di come farei io: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=96339&start=0 [/quote]

Confermo, e sottoscrivo, printf e sprintf sono da evitare come il diavolo, sono comodissime, ma sono molto pesanti come occupazione della flash e sono lentissime in esecuzione. Il motivo è che sono funzioni general purpose con una vasta gamma di opzioni e tipologia di dati diversi, il loro parser è molto grosso e ci mette molto tempo per decodificare il comando. Stessa cosa per le classi, sono molto comode per il programmatore, ma sono molto scomode per il compilatore, quando si lavora con i piccoli micro è meglio limitare al massimo l'uso del C++, anzi sarebbe meglio non usarlo per niente e limitarsi al C ANSI.

uwefed: E dove trovi la libreria? Come lo fa la libreria internamente? Ciao Uwe

la libreria floatToString.h la trovi proprio sulle guide di arduino con esempi di utilizzo http://www.arduino.cc/playground/Main/FloatToString non è forse affidabile per conversioni complesse, "This code has been deprecated by the discovery of dtostrf();" ma per la mia semplice conversione funziona e prende poco spazio. Qundi va verificato il risultato se è corretto altrimenti va sostituita.

Qualcuno ha trovato problemi con sprintf: If you have ever tried to use sprintf() on an Arduino to convert from a float to a string, you will notice it doesn't work. sprintf(buf,"%f", floatvar);

The above function will most likely return a "?" to your char buffer. If you google around, you'll see various functions that people have written to overcome this, but all of them seem broken in one way or another. The alternative is to use dtostrf(), a standard avr-libc function. This provides a simple, tested function to convert from a float to a string.

To use this function, simply replace sprintf() with dtostrf(), along with the self explanatory parameters below. dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf); As the function name suggests, this will also work for the conversion of doubles to strings.

ciao

This code has been deprecated by the discovery of dtostrf()

chi ha scritto quella libreria ha scoperto solo dopo l’esistenza di dtostrf() :smiley:

Salve ho provato con dtostrf

char buffer[20];
char *result;
float number=12345.12345;
result = dtostrf(number, 0, 5, buffer); 
Serial.println(result);
result = dtostrf(number, 2, 5, buffer); 
Serial.println(result);

ma il risultato è sempre lo stesso 12345.12300 !! Poichè sto utilizzando la libreria TinyGPS e le coordinate sono float, come posso fare? Grazie

sicuro non sia il float a perdere precisione? prova a stamparlo a video…

Se scrivo:

float number=12345.12345;
Serial.println(number);

quello che ottengo è 12345.12

Inoltre non ho capito cosa indica __width

char* dtostrf   ( double           __val,
                       signed char    __width,
                       unsigned char __prec,
                       char *            __s 
                    )

con Serial.print() puoi stampare fino a 4 cifre decimali:

Serial.print(number, 4);

12345.1234

Se provi a far giare questo sketch:

char buffer[20];
float number=12345.12345;
float num = 123.456789;
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  dtostrf(number, 12, 5, buffer); 
  Serial.println(buffer);
  Serial.println(number, 4);
  float temp = number - 12345.0;
  float decPart = temp*100000;
  Serial.println(decPart);
  
  dtostrf(num, 11, 3, buffer); 
  Serial.println(buffer);
  dtostrf(num, 11, 6, buffer); 
  Serial.println(buffer);
  Serial.println(num, 4);

  while(1);
}

Sembra che i float su arduino siano limitati alla 5a cifra decimale. di conseguenza dtostrf non può fare i miracoli.

Oltretutto se vedi num ha meno cifre intere e ne acquista un paio decimali quando usi dtostrf.

Una spiegazione rigorosa non ce l'ho...

Per quanto riguarda dtostrf():

width è la lunghezza minima che vuoi dare alla stringa considerando il punto e l'eventuale segno.

prec sono le cifre dopo la virgola. Sempre dall'esempio sopra noterai che in base alla precisione che selezioni, dtostrf ti fa l'arrotondamento.

[quote author=Federico Vanzati link=topic=80601.msg618104#msg618104 date=1323336586] Sembra che i float su arduino siano limitati alla 5a cifra decimale. di conseguenza dtostrf non può fare i miracoli. [/quote]

Il Reference dice che i float sull'Arduino sono limitati a 6/7 cifre decimali nel TOTALE: http://arduino.cc/en/Reference/Float

Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.

I numeri in virgola mobile "float" hanno solo 6-7 cifre cifre decimali di precisione. Questo indica il numero totale di cifre, non il numero di quelle alla destra del punto decimale. A differenza di altre piattaforme, dove puoi avere più precisione usando un tipo "double" (ad es. fino a 15 cifre), sull'Arduino, un "double" ha la stessa dimensione di un "float".

Adesso non ho il tempo per provare ma se fosse così in teoria un numero come 1.234567 o 12345.67 dovrebbero essere il massimo che si può avere come precisione decimale. Qualcuno può verificare?

la spiegazione è la notazione scientifica!

quindi 12345.12345 in float sarebbe 1.234512345 *1 0^4

abbiamo detto che la precisione massima dei decimali è 7, quindi diventa:

1.2345123 * 10^4

mistero risolto

peccato che non si può risolvere neanche con un double

Il limite non è di Arduino ma della matematica a 32 bit, i float sono rappresentati sotto forma di una mantissa 23 bit, un esponente a 8 bit e un bit di segno.
La mantissa è sempre un valore >1 e <2, ovviamente in forma binaria e questo spiega automaticamente perché il valore è sempre e comunque 1 virgola qualcosa che va moltiplicato per 2 elevato all’esponente, sempre in base 2, per ottenere il reale valore.
In realtà l’esponente dei float ha un bias del quale deve essere tenuto per fare le corrette conversioni e dipende dallo standard di rappresentazione adottato che non è uguale per tutti i compilatori, il più diffuso è il IEEE 754.
Questo tipo di rappresentazione con solo 23 bit per la mantissa limita il suo valore ad un massimo di 1,8388608 , la prima cifra 1 è implicita e non viene rappresentata nei 23 bit.
Dato che per effetto degli inevitabili arrotondamenti nei calcoli l’ultima cifra, intesa come valore in notazione base 10, della mantissa non è attendibile ecco che si è scelto di rappresentare il numero finale in decimale limitato alle sole ultime cinque cifre dopo la virgola se possibile perché un numero con più di una cifra prima della virgola porta via cifre decimali.
Per capirci meglio, un valore intero a 32 bit permette di rappresentare numeri fino a 12 cifre con segno, un float a 32 bit permette al massimo di rappresentare un numero a 7 cifre con segno di cui le prima intera e le successive cinque decimali (una viene ignorata per gli arrotondamenti), se gli interi diventano 2 i decimali diventano 4 e così via, per dirla più semplicemente un numero pari a 5.000.000,123 perde tutti i decimali nella notazione float a 32 bit, e questo vale per Arduino, ma anche per un superpc se usa matematica float a 32 bit.
Da notare che i numeri float permettono di rappresentare valori enormi, di gran lunga maggiori degli interi a 32 bit, per via dello loro natura esponenziale, un valore a 23 bit moltiplicato per 2 elevato alla 127 (valore massimo dell’esponente) corrisponde ad un numero a 150 bit (1.427 x 10^45), però tutti i bit dopo i primi 23 valgono 0 quindi la risoluzione è sempre limitata a +/- 8388608 valori diversi, cioè 23 bit.

"crocifiggetemi in sala mensa" ho postato prima di andare a riguardare (e studiare meglio) cos'è un float!