Salve ragazzi, facendo un pò di prove mi sono imbattuto in una cosa che reputo abbastanza strana ma non essendo programmatore forse è normale e sono io a non capire. In pratica ho provato a convertire una variabile float a integer ma ho notato che se i decimali iniziano per 0 poi il risultato non riporta di una unità. Ho riprovato facendo uno sketch nuovo ma il risultato non cambia:
void setup()
{
Serial.begin(9600);
int var1=int(variabile1*100); //moltiplica la variabile per 100 e converte da float a integer
int var2=int(variabile2*100);
Serial.println(var1); // restituisce 1815
Serial.println(var2); // restituisce 1804 perchè s'è fregato una unità????
}
void loop()
{}
La cosa mi sembra strana e vorrei capire perchè si comporta così....
Ho provato pure a mettere altre variabili in modo da fare un passaggio per volta, quindi prima la moltiplicazione e infine la conversione ma è uguale.
Non mi serve più usare questa conversione nello sketch che ho sotto mano ma oramai che ci sono non mi piace rimanere col dubbio di perchè avvengono queste cose, credo mi capirete....
Ragazzi, questa cosa è davvero assurda per me....
Ho rifatto lo sketch e funziona solo che ho moltiplicato per 1000 e diviso per 10...
float variabile2 = 18.05;
void setup()
{
Serial.begin(9600);
int var2=int(variabile2*1000/10); //moltiplica la variabile per 1000, divide per 10 e converte da float a integer
Serial.println(var2); // restituisce 1805, ora funziona... mah
}
Ho riprovato come mi hai detto ma restituisce semper 1804, non va:
int var2=(int)(variabile2*100);
Chi ci capisce qualcosa è bravo forte o io sono un somaro al quadrato ;D
E' un problema di approssimazione e sequenza di operazioni.. dovrei aprire il mio libro di C.
Tanto per curiosità prova a mettere il risultato dell'operazione in un float e in un secondo momento a farne il cast.
Del tipo
float tempVar= (operazioni con float);
int var=(int)tempVar;
Se mi ricordo domani butto un occhio sul libro.
Prova anche
int var=(int)((float)(operazioni con float));
errore di arrotondamento;
devi pensare che stai lavorando con: 1) numeri binari; 2) formati diversi di rappresentare i numeri.
Una spiegazione piú dettagliata non so darti.
Ciao Uwe
la rappresentazione in numeri a virgola mobile, secondo standard(IEEE 754), si fa così: si prende il numero e lo si divide per 2 finchè non ottien 1,qualcosa... ti memorizzi (ovviamente in binario):
1: quel qualcosa (mantissa) (23 bit per float, 52 per double)
2: l'esponente (ovvero il numero di volte che hai diviso per 2) (8bit per float, 11per double)
3: il segno (+ =0, - = 1) (1 bit)
molto probabilmente come mantissa viene un numero bello lungo: se non ci sta il C taglia la parte meno significativa (quella a destra).
Quando ritrasformi il numero "per esseri umani" in pratica fai:
1,mantissa*(2^esponente)*(-1*segno)
ed ecco perchè il tuo numero perde precisione... a causa del troncamento per far stare la mantissa nei bit specificati. (un'esponente troppo grande invece è un'overflow)
Mamma mia ragazzi quanto sono ignorante e quanto devo studiare... ringrazio tutti per aver fornito spiegazioni, mi metto subito a leggere con la speranza di capirci qualcosa. Confesso che appena ho letto mantissa mi è venuto in mente una medusa o comunque un animale esotico :)
@lesto
eh sì, ho peccato di leggerezza facendo la prova con gcc sul mio sistema (linux 64bit) dove, da un rapido controllo con sizeof(), vedo che un double occupa 64bit e un float 32bit.
con avr-gcc, da una rapida ricerca su google, invece, risulta che float, double e finanche long double sono tutti a 32 bit.