Conversione decimale-binario in C
Ciao a tutti, mi chiamo Gloria ed è la prima volta che posto un topic di informatica. Sto lavorando col linguaggio c e mi trovo a dover capire questo programma .
- Diciamo che volevo chiedere delucidazioni riguardanti alla parte colorata in verde in quanto non capisco come viene trattato l'esponente. Quello che ho capito è che r è la mantissa , ed e è l'esponente, allora il risultato deve essere r*$10^$.
In sostanza non riesco a capire quello che fa il proff nel programma.
Per quantola parte che riguardante la trattazione della stringa s non ci sono problemi prechè scorro tutti i caratteri della stringa finoa che trovo il punto decimale ed una volta trovato il punto lavoro sulla parte decimale fino ad arrivare all'esponente.
- Inoltre volevo chiedere cosa indica bool sign=false.
Grazie a tutti in anticipo!!!
- Diciamo che volevo chiedere delucidazioni riguardanti alla parte colorata in verde in quanto non capisco come viene trattato l'esponente. Quello che ho capito è che r è la mantissa , ed e è l'esponente, allora il risultato deve essere r*$10^$.
In sostanza non riesco a capire quello che fa il proff nel programma.
Per quantola parte che riguardante la trattazione della stringa s non ci sono problemi prechè scorro tutti i caratteri della stringa finoa che trovo il punto decimale ed una volta trovato il punto lavoro sulla parte decimale fino ad arrivare all'esponente.
- Inoltre volevo chiedere cosa indica bool sign=false.
Grazie a tutti in anticipo!!!
#include <stdio.h> #include <float.h> #include <math.h> #include <time.h> #define BIN double s2f(char *s) { static double etens[9] = {10.0, 100.0, 10000.0, 100000000.0, 10e16, 10e32, 10e64, 1e128, 10e256}; bool sign = false; double r = 0; double mult = 1.0; if (*s == '-' ) { s++; sign = true; } else if (*s == '+') s++; while ((*s>='0') && (*s <='9')) { r = r*10+*s-'0'; s++; } if (*s=='.') { s++; while ((*s>='0') && (*s <='9')) { mult /= 10.0; r += mult*(*s-'0'); s++; } } [color=green]if ((*s=='e') || (*s=='E')) { int exp = 0, idx=0; bool esign = false; s++; if (*s == '-') { esign = true; s++; } while ((*s>='0') && (*s <='9')) { exp = exp * 10 + (*s-'0'); s++; } #ifdef BIN while (exp) { if (exp & 1) if (esign) r /= etens[idx]; else r *= etens[idx]; exp >>= 1; idx++; } #else if (esign) exp = -exp; if (exp) r *= pow(10.0, exp); #endif [/color] } return (sign ? -r : r); } int main(int argc, char *argv[]) { char *sx[]= { "pippo", "-20epippo", "0.2e0", "3ee23", "-3.5E-12", "0001e12" }; clock_t c = clock(); printf("%f\n", CLOCKS_PER_SEC); printf("%li\n", c); int i; for (i=0; i<6; i++) { double x; for (int j = 0; j < 1000000; j++) s2f(sx[i]); printf("%s -> %lg \n", sx[i], s2f(sx[i])); sscanf(sx[i],"%lf", &x); printf("%s -> %lg \n", sx[i], x); } c = clock(); printf("%li\n", c); }
Risposte
Mi pare comunque incredibile che questo codice sia stato scritto da un professore essendo uno strano mix di C e C++ e con l'uso, a mio parere insensato, del preprocessore.
In ogni caso.
Una e o E alla fine di un numero viene solitamente interpretata come l'inizio di un esponente. In questa prima parte si cerca quindi di leggere questo esponente. esign serve a stabilire la presenza o meno di un segno. Non è però completo perché ignora la possibile e facoltativa presenza del segno '+' e verifica solo la presenza di '-'. Il codice successivo ti dovrebbe essere invece abbastanza chiaro perché usato praticamente ovunque nel resto del codice. A questo punto deve moltiplicare tutto il codice per 10^{exp}
Questa parte del codice è più criptica e la presenza del preprocessore non aiuta. Se BIN è stato definito, allora esegue l'operazione in un modo un po' particolare che ti spiegherò dopo. Se invece non fosse definito usa semplicemente la funzione pow per calcolare l'esponente.
Considera l'esponente nella forma
$exp = b_0 * 1 + b_1 * 2 + ... + b^n * 2^n$.
Il tuo numero deve quindi essere moltiplicato per
$10^exp = 10^{b_0^1 + b_1*2 + ... + b^n * 2^n} = 10^{b_0 * 1} * 10^{b_1 * 2} * ... * 10^{b_n * 2^n}}$
A questo punto è ovvio che è sufficiente moltiplicare tra di loro le potenze nella forma $10^{2^i}$ quando $b_i$ è diverso da $0$. È esattamente quello che fa nel codice quando BIN è stato definito.
In ogni caso.
if ((*s=='e') || (*s=='E')) { int exp = 0, idx=0; bool esign = false; s++; if (*s == '-') { esign = true; s++; } while ((*s>='0') && (*s <='9')) { exp = exp * 10 + (*s-'0'); s++; }
Una e o E alla fine di un numero viene solitamente interpretata come l'inizio di un esponente. In questa prima parte si cerca quindi di leggere questo esponente. esign serve a stabilire la presenza o meno di un segno. Non è però completo perché ignora la possibile e facoltativa presenza del segno '+' e verifica solo la presenza di '-'. Il codice successivo ti dovrebbe essere invece abbastanza chiaro perché usato praticamente ovunque nel resto del codice. A questo punto deve moltiplicare tutto il codice per 10^{exp}
#ifdef BIN while (exp) { if (exp & 1) if (esign) r /= etens[idx]; else r *= etens[idx]; exp >>= 1; idx++; } #else if (esign) exp = -exp; if (exp) r *= pow(10.0, exp); #endif
Questa parte del codice è più criptica e la presenza del preprocessore non aiuta. Se BIN è stato definito, allora esegue l'operazione in un modo un po' particolare che ti spiegherò dopo. Se invece non fosse definito usa semplicemente la funzione pow per calcolare l'esponente.
Considera l'esponente nella forma
$exp = b_0 * 1 + b_1 * 2 + ... + b^n * 2^n$.
Il tuo numero deve quindi essere moltiplicato per
$10^exp = 10^{b_0^1 + b_1*2 + ... + b^n * 2^n} = 10^{b_0 * 1} * 10^{b_1 * 2} * ... * 10^{b_n * 2^n}}$
A questo punto è ovvio che è sufficiente moltiplicare tra di loro le potenze nella forma $10^{2^i}$ quando $b_i$ è diverso da $0$. È esattamente quello che fa nel codice quando BIN è stato definito.
Grazie mille per la risposta. Ora mi è tutto molto più caro!!!!Grazie ancora.