Go Down

Topic: [risolto]Conversione hex a dec (Read 214 times) previous topic - next topic

centurione_agrippa

Dec 07, 2019, 07:14 pm Last Edit: Dec 09, 2019, 11:00 am by centurione_agrippa
Salve ragazzi, ho fatto le mie ricerche nel forum ed ho adattano ciò che mi serviva. Devo fare la conversione da hex a decimale. Non so dove sbaglio, ho fatto varie prove con numeri sballati , potreste darci uno sguardo ?
Code: [Select]
int id_dec = 0;
   int val = 0;
   String id_string= incString.substring(0,index);
   
   for(int i=0; i<3; i++){
      if(id_string[i] == "A"){
         val = 10;
      }else if (id_string[2-i] == "B"){
         val = 11;
        } else if (id_string[i] == "C"){
          val = 12;
          }else if (id_string[i] == "D"){
           val = 13;
           }else if (id_string[i] == "E"){
            val = 14;
            }else if (id_string[i] == "F"){
             val = 15;
             } else {
                 val = id_string[i];
                 
                }
     id_dec = (int)val * pow(16,i)+ id_dec;
   
    }

Il numero in esadecimale è di tre lunghezze per esempio 19B

Silente

Per me il problema é la else finale. Il valore del carattere che indica una cifra non é uguale alla cifra che indica, ma sono comunque in sequenza crescente (se '0'=50 allora '1'=51, '9'=59). Quindi, sperando che contenga solo cifre o lettere, modificherei l'assegnamento in
Code: [Select]
val=in_string[i] -'0'
Poi modificherei il tutto usando solo due if al posto di tutte quelle if else, ma é un'altra storia
Dove va un numero va una variabile, una funzione e/o  un test.
Per ottenere devi spiegare

Strumenti/Formattazione automatica fino alla morte!
Cristianesimo:bibbia='C':K&R

centurione_agrippa

Non capisco perché il confronto con l'if è sempre falso. Per esempio se ho 19B quando verifico che B == "B" è falso.

docdoc

#3
Dec 08, 2019, 12:24 pm Last Edit: Dec 08, 2019, 12:25 pm by docdoc
Scusa, ma è tutto sbagliato.
Provo a spiegarti, per non darti la "pappa pronta" e portarti a capire da solo:

Code: [Select]
   if (id_string[i] == "A") {
Qui confronti un carattere con una stringa. In C non puoi farlo.
Devi quantomeno modificarlo per confrontare il carattere con un carattere quindi non "A" ma 'A'.

Code: [Select]
} else if (id_string[2 - i] == "B") {
Che è questo "2 - i"?? Lascia solo "i" come tutti gli altri simboli.

Code: [Select]
val = id_string[i];
Qui, come ti ha scritto anche Silente, stai prendendo il valore ASCII del carattere, non il suo valore. Devi fare la modifica che ti ha consigliato.

Code: [Select]
id_dec = (int)val * pow(16, i) + id_dec;
Anche questo è sbagliato. Il primo carattere della stringa (con i=0 per intenderci) è quello più significativo quindi va moltiplicato per 16^2 non per 16^i che significa 16^0! Devi mettere qui il "2 - i"...
Inoltre il cast "(int)" è superfluo in quel punto, "val" p già intero.

Una cosa che invece non è colpa tua è la "pow()", che restituisce un float e quindi devi fare qui il cast a "(int)", ma purtroppo è nota per dare problemi di decimali su Arduino, infatti "pow(16,2)" non dà 256 come atteso, ma dato che di fatto restituisce 255.99990844 troncando all'intero avresti 255!
Bisogna aggiungere un decimale per avere il valore intero corretto, esempio:

val * (int)(0.1+pow(16, 2-i))

Tutto questo si può anche fare in un modo molto più rapido ed elegante, ma inanto modifica il tuo programma in base a quello che ti ho indicato, e quando funziona fammi sapere se vuoi la soluzione più rapida e breve, e te la posto ;)
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

centurione_agrippa

#4
Dec 08, 2019, 04:56 pm Last Edit: Dec 08, 2019, 06:05 pm by centurione_agrippa
grazie ai vostri suggerimenti tutto funziona. Qual'è la soluzione più rapida ? :)  Avevo letto che esiste una funzione strtol ma che non avevo capito molto bene come funzionasse

Datman

#5
Dec 08, 2019, 08:46 pm Last Edit: Dec 08, 2019, 08:52 pm by Datman
Al posto di quel pesante pow non si può mettere un if/else o switch/case che moltiplichi per 1, 16, 256, ottenendo un bellissimo int?
Altrimenti un for che moltiplichi per n volte, da 0 a 2, per 16, ottenendo ancora una moltiplicazione per 1, 16, 256.
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

Silente

Potrei dire una caxxata, ma io normalmente per passare da decimale a binario faccio così
Code: [Select]

int valore=0;
char stringa[dim];
//stringa contiene solo caratteri corrispondenti a cifre
for (byte i=0;i<dim;i++)
valore=valore*10+(stringa[i]-'0');

Dove stringa -'0' é il valore della nuova cifra, non potrei fare qualcosa di simile in base 16?(dopo aver opportunamente calcolato il valore della cifra, ovviamente)

Per quanto riguarda il valore della cifra tutti quelli if non servono. Come i numeri anche le lettere sono in sequenza, quindi come se il carattere é compreso tra '0' e '9' tu ottieni direttamente il valore facendo carattere-'0'... Se il carattere é compreso tra 'A' e 'F' la cifra é solo 10+carattere- 'A'
Dove va un numero va una variabile, una funzione e/o  un test.
Per ottenere devi spiegare

Strumenti/Formattazione automatica fino alla morte!
Cristianesimo:bibbia='C':K&R

centurione_agrippa

Potrei dire una caxxata, ma io normalmente per passare da decimale a binario faccio così
Code: [Select]

int valore=0;
char stringa[dim];
//stringa contiene solo caratteri corrispondenti a cifre
for (byte i=0;i<dim;i++)
valore=valore*10+(stringa[i]-'0');

Dove stringa -'0' é il valore della nuova cifra, non potrei fare qualcosa di simile in base 16?(dopo aver opportunamente calcolato il valore della cifra, ovviamente)

Per quanto riguarda il valore della cifra tutti quelli if non servono. Come i numeri anche le lettere sono in sequenza, quindi come se il carattere é compreso tra '0' e '9' tu ottieni direttamente il valore facendo carattere-'0'... Se il carattere é compreso tra 'A' e 'F' la cifra é solo 10+carattere- 'A'
ci proverò

nid69ita

#8
Dec 09, 2019, 11:30 am Last Edit: Dec 09, 2019, 11:43 am by nid69ita
Magari usando le librerie del C si risolve con una istruzione: strtol
long valore=strtol(stringa,NULL,16);

Ovviamente stringa non è una variabile String ma devi avere una stringa classica del C
Converti String in un array di char con Stringa.toCharArray()
Code: [Select]
char cstr[20];
String id_string=incString.substring(0,index);
id_string.toCharArray(cstr,20);
long valore=strtol(cstr,NULL,16);


Forse poi si può  evitare una ulteriore String per avere solo un pezzo del testo:
Code: [Select]
char cstr[20];
id_string.toCharArray(cstr,20);  // la prendo tutta
cstr[index]='\0';                // taglio stringa a posizione index
long valore=strtol(cstr,NULL,16);
my name is IGOR, not AIGOR

Datman

ci proverò
Tutto quello che hai riportato prima lo avevamo già letto! Nell'email di notifica ho faticato per trovare che cosa avevi aggiunto! :(
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

docdoc

grazie ai vostri suggerimenti tutto funziona. Qual'è la soluzione più rapida ? :)  Avevo letto che esiste una funzione strtol ma che non avevo capito molto bene come funzionasse
Si, allora, sempre per farti capire meglio, intanto butta via le variabili String perché sono sicura fonte di instabilità: devi farlo sempre, sono altamente sconsigliate su Arduino, devi usare le "stringhe C".

Quindi una prima soluzione simile alla tua ma senza "String" e più "compatta" e generica (funziona anche con stringhe di lunghezza diversa da 3) è questa:

Code: [Select]

void setup() {
  Serial.begin(9600);

  char str[] = "19B";
  Serial.println(hex2int(str));
}

void loop() {

}

int hex2int(char* str)
{
  int val = 0; // Valore totale
  int ex = 1;  // Moltiplicatore per la cifra hex
  // Nel for parto dalla cifra meno signfiicativa
  for (int i = strlen(str)-1; i >=0 ; i--) {
    int delta = '0';
    if ( str[i] >= 'A' ) // Se è una lettera parto da 10
      delta = 'A' - 10;
    val += (str[i] - delta) * ex;
    ex *= 16; // Aggiorno il moltiplicatore
  }
  return val;
}



Ma quella più pratica e rapida è questa, e proprio con la strtol(): :)

Code: [Select]

void setup() {
  Serial.begin(9600);

  char str[] = "19B";

  Serial.println(strtol(str,0,16));
}

void loop() {

}

Il primo parametro è la stringa di input, il secondo è un eventuale puntatore (puoi ottenere il puntatore all'ultimo carattere convertito, se non ti interessa metti zero) e l'ultimo la base numerica di conversione (16 = esadecimale).
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

centurione_agrippa

#11
Dec 09, 2019, 11:28 pm Last Edit: Dec 10, 2019, 04:18 am by gpb01
Si, allora, sempre per farti capire meglio, intanto butta via le variabili String perché sono sicura fonte di instabilità: devi farlo sempre, sono altamente sconsigliate su Arduino, devi usare le "stringhe C"........
Una volta completato il tutto cerco di ottimizzarlo

Datman

Caro centurione, anche tutto questo l'abbiamo già letto!!! Perché ripeti sempre tutto il messaggio precedente??? Non serve, ingombra, da fastidio soprattutto leggendo dal telefonino ed è ancora più fastidioso nelle notifiche via email!

Spero di essere stato chiaro, questa volta.
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

gpb01

#13
Dec 10, 2019, 04:19 am Last Edit: Dec 10, 2019, 04:19 am by gpb01
>centurione_agrippa: Quando si quota un post, NON è necessario riportarlo (inutilmente) tutto; bastano poche righe per far capire di cosa si parla ed a cosa ci si riferisce. Gli utenti da device "mobile" ringrazieranno per la cortesia ;)

Guglielmo

P.S.: Ho troncato io il lunghissimo QUOTE del tuo post #11
Search is Your friend ... or I am Your enemy !

Go Up