Stranezza conversione da float a integer

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:

float variabile1 = 18.15; float variabile2 = 18.05;

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 }

void loop() {}

Non so se cambia qualche cosa, ma la sintassi corretta per un cast in C è: int i=(int)(valore float); Ciao

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));

ciao

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

se definisci var1 e var2 di tipo double invece di float, funziona

evidentemente vuole la doppia precisione

gli int sono a 16 bit, mentre i float a 32 bit

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)

fonte (e approfondimento): http://it.wikipedia.org/wiki/IEEE_754

buono studio ;)

ps: i float sono a 32bit, i double a 64... arduino però afferma che anche per i double usano 32bit... adalgisio hai fatto la prova su un compilatore tradizionale o su arduino? http://www.arduino.cc/en/Reference/Float http://www.arduino.cc/en/Reference/Double

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.

ok, era giusto per sapere se era sbagliata la documentazione, a volte capita :)