Newsgroup: it.comp.lang.c++
Titolo: sulla estrazione della mantissa e dell'esponente da un numero

Dovendo estrarre da un numero la sua mantissa (come intero) e
l'esponente [value = mantix * 10^exp] mi sono ingegnato questo codice
non molto efficiente dal mio punto di vista.
Per semplicita' presuppongo che value > 0
template<class T>
void extract(const T & value){
	short exp = 0;			// esponente
	T v = value;
	if(value > 1)
		for( ; v > 10; exp ++) v /= 10;
	else
		for( ; v < 1; exp --) v *= 10;
	// faccio un cast a short perche' so che 1 < v < 10
	T mantix = (unsigned short) v;		// mantissa (si scrivera' cosi'?)
	T resto = v - mantix;
	for( ; resto != 0; exp --){
		resto *= 10;
		mantix = mantix * 10 + (unsigned short) resto;
		resto -= (unsigned short) resto;
		}
	}
Mi rendo pero' conto che la condizione resto != 0 potrebbe non
funzionare, ma in questo caso basterebbe sostituire quella riga con
questa:
#define	MAXPRECDGT	18
for(unsigned char prec = 1; prec < MAXPRECDGT && resto != 0; prec ++,
exp --)
oppure con
#define	MAXPREC	0.0001		// 'pseudo-precisione'
for(unsigned char prec = 1; prec < MAXPRECDGT && resto > MAXPREC; prec
++, exp --)
Considerazioni;
- Sta di fatto che se gli passo un intero, questo codice fa tante cose
per niente quando la risposta e' banale: mantix = value, exp = 0...
 A questo potrei ovviare separando i due metodi: uno per gli unsigned
long e l'altro per i long double, anche se preferirei farne a meno.
- Similmente se gli passo un long double (ad es. 1.2345e+4000), il tempo
di esecuzione e' 'enorme'...
 E a questo non ho trovato soluzione (magari esistono gia' due funzioni
che mi consentano di fare quello che voglio, ma non le conosco, o
meglio, questo codice l'ho buttato giu' in poco tempo, senza curarmi se
esistono gia' le funzioni summenzionate: quando vado a casa
controllo...)
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 ...
Esiste una funzione standard 'frexp' definita in <cmath> che fa gia'
quello che tu chiedi per i double; e lo fa in modo assai piu'
intelligente visto che la mantissa e' moltiplicata per un esponente di
2 e non di 10.  E' un compito?  (Hint - se vuoi l'esponente in base 10
perche' non chiami log10 dopo un controllo per 0 e numeri negativi)?
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy          loreti at pd dot infn dot it

 void extract(const T & value)
oppure, ho pensato, imposto un flag dall'esterno (e forse faro' proprio
cosi')
template <class T>
void extract(const T & value, const bool & isInteger)



Lascia stare i template che qui non servono; basta dichiarare due funzioni
con stesso nome e parametri di tipo diverso:
void extract(const double& val) { ... }
void extract(const int& val) { ... }
e il compilatore chiamerą la funzione in base al tipo determinato al momento
della compilazione.
Rif. Stroustrup Capitolo 7.4, overload dei nomi di funzione.

 con stesso nome e parametri di tipo diverso:
si' , c'i avevo pensato anch'io poi (in principio era per avere un'unico
metodo)


Seconda versione
#define	PREC	1e-5
void extract(const double & value){
   int exp = floor(log10(value));
   double mant = value / pow10(exp);
   for( ; fmod(mant, 1) > PREC; exp --)
      mant *= 10;
   }
fmod non va molto bene - e neppure modf - perche' non e' preciso (per
questo ho dovuto
aggiungere PREC: 123456 mod 1 mi dava qualcosa del tipo 1e-15...). Credo
proprio che
mi terro' i miei 8 byte (non senza prima averci riprovato un po').
Grazie a tutti quelli che mi hanno aiutato finora!
