Semplice calcolo.. dove sbaglio?

Senza entrare nel merito del programma principale, dato che mi sta dando un errore, ho estrapolato questa semplice operazione per farci delle prove sopra, dato che mi da un risultato che non capisco. void setup() { delay(1000); Serial.begin(9600); Serial.print(30*60*1000); }

void loop() { }

Il risultato dovrebbe essere 1800000 invece ottengo 30528. Ho volutamente eliminato le variabili di appoggio per evitare problemi legati ai vari type, ma il risultato non cambia.

Il GCC esegue la promozione automatica ad intero in mancanza di specifiche utente, in particolare per i calcoli diretti, cioè il conto viene fatto con solo 16 bit di risoluzione. Il tuo conto richiede almeno 24 bit di risoluzione per poter presentare il risultato, quindi o usi varibili long oppure metti almeno un valore float nel conto con i numeri, p.e. 30.0 invece di 30, e vedrai che il risultato diventa quello atteso.

astrobeed: Il GCC esegue la promozione automatica ad intero in mancanza di specifiche utente, in particolare per i calcoli diretti, cioè il conto viene fatto con solo 16 bit di risoluzione. Il tuo conto richiede almeno 24 bit di risoluzione per poter presentare il risultato, quindi o usi varibili long oppure metti almeno un valore float nel conto con i numeri, p.e. 30.0 invece di 30, e vedrai che il risultato diventa quello atteso.

Ho fatto una prova: se metto direttamente i numeri 30.0 , 60.0 e 1000.0 ottengo il risultato ottenuto. Se invece utilizzo una (o più) variabili di appoggio (come vorrei), nonostante la dichiaro come long, il risultato è quello errato:

void setup()
{
  delay(1000);
  Serial.begin(9600);
  long pippo;
  pippo = 30*60*1000;
  Serial.print(pippo);
}

void loop()
{
}

Si ma se non fai un cast al conto con solo i numeri non importa che la variabile sia long, il conto viene sempre fatto a 16 bit perché quella è la precisione assegnata di default.

pippo = (long)30*60*1000;

oppure puoi fare così:

  long pippo = 30;
  pippo = pippo*60*1000;

Visto che un termine del calcolo è long anche per il calcolo viene usata la precisione a 32 bit.

Beh, sicuramente le mie conoscenze di programmazione sono scarse (vedi “cast” che non so cosa sia), comunque mi sa che faccio prima a mettere il codice “vero” così forse l’aiuto calzerà più a pennello:

long msFaderLuci; //Tiene in memoria il trascorrere del tempo relativo al fading delle luci
byte minFaderLuci; //Durata del fading impostato espresso in Minuti

void setup()
{
  delay(1000);
  msFaderLuci = 9010; //imposto il valore manualmente per fare delle prove
  minFaderLuci = 30;
  Serial.begin(9600);
  long pippo; //uso una variabile d'appoggio per vedere il risultato prima di fidarmi..
  pippo = msFaderLuci+(minFaderLuci*60*1000/255);
  Serial.print(pippo);
}

void loop()
{
}

Il fatto è che non vorrei dichiarare long delle variabili se non ce n’è bisogno. In particolare la variabile minFaderLuci è un byte perchè conterrà a regime dei numeri piccoli.

Ho capito adesso.... Ho modificato la riga come segue: pippo = msFaderLuci+((long)minFaderLuci*60*1000/255); Anche se msFaderLuci è dichiarato come Long, mi sa eseguiva comunque un calcolo tra int e poi lo sommava ad un long. Adesso funziona, attendo solo conferma di sapere se ho fatto bene :)

Già che ci sono... devo adottare qualche accorgimento dato che nel calcolo c'è una divisione?

Le variabili vanno dimensionate come serve, però tocca ricordarsi che le operazioni tra tipi diversi danno risultato una precisione pari a quella del tipo maggiore utilizzato. Esempio, un prodotto tra variabili byte (8 bit) fornisce un risultato a 8 bit, la parte in eccesso viene troncata, un prodotto tra una variabile int e una byte fornisce un risultato a 16 bit, e così via. Il casting permette di modificare la dimensione di una variabile prima del calcolo, ovviamente anche la variabile che riceve il valore calcolato deve essere di opportune dimensioni altrimenti il valore viene troncato lo stesso.