Newsgroup: it.comp.lang.c++
Titolo: il modulo non va bene.

salve a tutti:
per motivi di dimensioni dei dati sono stato costretto a cambiare un tipo di
dato da unsigned long int a double.
solo che in una funzione facevo l'operazione di modulo % (modulo 100 per
l'esattezza) su quel dato, in modo da ottenere solamente le due cifre più a
destra del numero.
Come posso ottenere le ultime due cifre di un double?
grazie
Giulio

 wrote in message
BBQEa.15491$Fr5.3...@tornado.fastwebnet.it...

Vuoi le due cifre più a destra del double oppure le due cifre più a destra
della parte intera di un double?
Se vuoi la seconda puoi castare il tipo double in un intero e poi applicare
il modulo:
double d=1389.234;
return static_cast<int>(d)%100;
l'espressione static_cast<int>(d) resituisce l'intero 1389 mentre
l'espressione 1389%100 restiuisce l'intero 89.
Se vuoi invece ottenere le due cifre più a destra di un numero double la
soluzione più semplice che mi viene in mente è quella di moltiplicare per 10
il numero reale (chiamiamolo d) finché
static_cast<double>(static_cast<int>(d))==d (ovvero fino a che la parte
intera di d e d non coincidono, ovvero tutte le cifre decimali sono state
portate a sinistra della virgola) dopodiché applichi l'istruzione precedente
applichi il modulo sulla parte intera di d esattamente come prima.
Esiste sicuramente una via più breve ma questo è tutto ciò che mi viene in
mente dopo un esame di elettrotecnica.
Ciao.

 return static_cast<int>(d)%100;
questo non e' proprio corretto.
Infatti l'amico ha detto che e' stato costretto a passare
da unsigned long int a double per motivo di dimensione di dati,
quindi sembra di capire che aveva dei numeri piu' grandi di 2^(32).
Facendo il cast ad int di un numero double maggiore di 2^(32) ottieni
un numero che non ha nulla a che vedere con quello che stai cercando.
La cosa piu' sicura, secondo la mia modestissima opinione,
e' usare le funzioni di math.h :
la fdiv(double x, double y) che calcola quanto rimane
togliendo da x il valore y un numero intero di volte (il
corrispondente di % nei double)
e la funzione round(double x) che calcola la parte intera (ma in double)
che si avvicina di piu' ad un double x.
in questo caso potresti fare, dato x:
double t = fdiv(x,100.0);
// cosi se x=653.0522 hai t=53.0522
e poi
int dd = (int) round(t);
che ti da dd=53
comunque devi stare attento a come tratti i numeri double
che sono molto vicini ad un intero. La mia soluzione (con round())
potrebbe non andarti bene. Guarda anche la trunc().
Tieni inoltre conto che a volte i double ottenuti attraverso
qualche calcolo possono "sembrare" interi, ma magari
internamente invece di x=76.00 hai x=75.999999999999999725
ciao,
g.

Giovanni Resta <g.r...@iit.cnr.it.nospam> wrote in message
3EE48547...@iit.cnr.it.nospam...

Direi che hai ragione. Non ci avevo pensato.

 comunque devi stare attento a come tratti i numeri double
Tanto vale trasformalo in stringa e prendere direttamente i 2 caratteri 
che servono... Mi sa che č anche piů veloce.
-- 
Luc.

 wrote

In pratica se usi double per ovviare al limite di int allora credo che tu
non sia interessato alle cifre decimali.
Quindi tu vuoi:
da 49636.0 ottenere 36 e
da 49636.421 ottenere sempre 36
giusto?
Una possibile soluzione e' questa:

 Una possibile soluzione e' questa:
Mi e' scappato un tasto, continuo...
double n=49636.421;
int last_two=int(floor(fmod(n,100)));
in pratica da 49636.421 ottengo 36.421 che poi faccio diventare 36 e
converto in int.
NOTA BENE: I numeri double sono numeri "non precisi", bisogna stare attenti
a come li si tratta.
Il codice che ti ho postato *NON* funziona in tutti i casi....
SOLUZIONE:
Se tu non te ne fai nulla di avere numeri decimali, perche' non usi un
classe che rappresenti un tipo di dato intero con piu' precisione... Ce ne
sono tante in giro su internet. Ad esempio questo e' quello che succede con
una di queste classi che mi sono implementato io come esercizio:
<CODE>
CInfInt n=79;
for(int i=1;i<250;++i){
    n*=i;
    n+=99;
}
cout << "Ora n vale: " << n << endl;
cout << "Le ultime due cifre intere sono: " << (n%100) << endl;
</CODE>
e' l'output e' il seguente:
<OUTPUT>
Ora n vale:
+322134601263478688378257049808145198753021646764100557912439479791151807226
3149618816554251460946253987534219462366709829409493351199917753684268417883
7234562454617509151142974443384589597955972820404739723361996332546676891948
9286451572360060830072954011142034619638263819490487082694114894734440443295
7219460516255060566376969500389790176047864047482155017350668891070131447085
7206558407844194395647326392957294561409396539422185865837200521091659483575
84186460021123732864591674092219905230
Le ultime due cifre intere sono: +30
</OUTPUT>
Credo che questa sia la soluzione migliore, in questo modo puoi inoltre
andare oltre al limite dei double....
Tommy

 che servono... Mi sa che è anche più veloce.
Si, e' una soluzione ;-)
Sul fatto che sia piu' veloce rispetto al metodo descritto da Giovanni pero'
ho qualche dubbio, ma non ho voglia di fare prove e quindi mi limito ad
avere qualche dubbio...
Tommy

 84186460021123732864591674092219905230
LOL.  Ma il tipo CInfInt quanti byte usa?

 LOL.  Ma il tipo CInfInt quanti byte usa?
Ne usa quanti ne servono...
L'ho chiamato CInfInt in quanto teoricamente e' un tipo di dati
"infinito"... in pratica non lo e', ma funziona fino a quando c'e' memoria a
disposizione ;-)
Questa classe l'ho implementata come esercizio, oramai parecchi anni fa...
C'e' di meglio in giro in termini prestazionali (se la cava abbastanza cmq),
ma ci sono cosi' tanto affezionato che la uso spesso (e' stata una delle mie
prime classi scritte in C++ e mi diede un mucchio di soddisfazione!).
Ad esempio se gli faccio calcolare il fattoriale di 50000:
<CODE>
CInfInt n=1;
for(int j=2;j<=50000;++j)
    n *= j;
cout << "Ora n ha " << n.GetRealSize() << " cifre!" << endl;
</CODE>
mi dice:
Ora n ha 213,237 cifre!
(apri un file di testo di circa 200K e guardalo, piu' o meno il numero e'
lungo cosi'! (non lo posto per *ovvi* motivi!)
Questo usera' abbastanza memoria! Ma difficilmente sara' troppa su di un PC
moderno.... (io ho 512MB + 2GB di memoria virtuale e prima di finire tutta
questa memoria.........)
Al contrario, anche su PC moderni sono i tempi di esecuzione a lasciare a
desiderare.... (il calcolo del post di prima era assolutamente immediato,
questo invece, su di un 1.8Ghz, richiede un minimo di pazienza!).
Tommy

 prime classi scritte in C++ e mi diede un mucchio di soddisfazione!).
Molto bello.
Immagino allochi dinamicamente la memoria grezza e poi esegua le varie
operazioni con le operazioni bit a bit.
E' esatto?

 E' esatto?
Si, per motivi di prestazioni un numero che sta in un byte ne occupa 20
(questa e' la quantita' minima che alloca). Appena i 20 non bastano si passa
a molti di piu', appena questi utlimi non bastano ad ancora molti di piu', e
cosi' via.... Se allocassi 1 byte, poi 2, poi 3 etc... non sarebbe il
massimo, questo rallenterebbe.
Quindi io alloco memoria "grezza", poi spesso solo una parte di questa viene
utilizzata. Ho cercato un compromesso tra spreco di memoria e prestazioni.
n.GetRealSize() serve per sapere quante cifre occupa il numero, poi esistono
altri metodi per sapere quanti bytes occupa il numero e quanti bytes sono
allocati; questi ultimi due spesso non coincidono per quello che ti ho detto
sopra.
Esiste un meccaniscmo simile per ridurre la quantita' di memoria allocata
quando questa diventa troppa.
Sono implementati tutti gli operatori standard che si applicano agli int. In
piu' ci sono altri metodi speciali tipo Sqrt(), etc... Avendo tempo di
riscriverla potrei fare meglio, ti ripeto l'ho fatta agli inizi, ma mi ci
sono cosi' affezionato che, a meno che non ne abbia la necessita', voglio
evitare di riscriverla ;-)
Tommy

 l'esattezza) su quel dato, in modo da ottenere solamente le due cifre piů


 alla fine risparmierei anche memoria..
Si in effetti non ti servono numeri... Un array, un vector, o una stringa o
una struttura o... etc.. vanno tutti piu' che bene.
Tommy

 ho qualche dubbio
Le operazioni sui float/double sono ben lente... Ma bisognerebbe fare dei 
benchmark. Comunque se non è time critical, sicuramente sarà precision-
critical, quindi meglio il metodo stringa. 
-- 
Luc.