Newsgroup: it.comp.lang.c
Titolo: parte decimale di un numero

ciao a tutti.
io son un programmatore vb, ex programmatore C (eh sì, mi è dispiaciuto
mollarlo).
ora voglio fare una cosa particolare con un numero double: come faccio
ad ottenere la parte decimale
senza utilizzare cast o funzioni di coversione?? in realta ho una data
ed in vb la data è un double.
solo che mi perdo alcuni decimali, quindi vorrei ottenere solo la parte
decimale.
in realtà mi lascia perplessa un altra cosa: se ottengo solo la parte
decimale (magari trasformata in parte "Intera" tramite uno bit-shift) il
numero corrisponde, non è vero che è uguale alla parte decimale.
quindi, come vengono interpretati/scritti i numeri decimali?
grazie
Daniele


Ma questa domanda riguarda il VB o il C?
se riguarda il VB dovresti porla su it.comp.programmare o qualcosa di 
simile dove sono piu' esperti di VB.
io l'ultimo basic che ho usato e' stato quello del commodore 64,
quindi non so che funzione usare in VB per ottenere la
parte decimale. Magari qualcosa tipo x - TRUNC(x) dove TRUNC (o altra 
funzione simile)
ottiene la parte intera per troncamento. Ci sara' pure un help in linea...
Invece scordati proprio di convertire una parte decimale in intera
mediante shift binari.
Uno shift binario corrisponde ad una moltiplicazione per una
potenza (positiva o negativa) di 2. Se tu vuoi trasformare
un numero da decimale (in base 10) a intero devi moltiplicarlo
per delle potenze di 10, non di 2.
Cosi' come puoi scordarti di ottenere in modo semplice la parte
decimale di un numero manipolando la codifica interna del double.
I numeri in floating point di solito vengono memorizzati in un formato
composto da una mantissa (normalizzata) in base 2
e un esponente (in base 2!!).
Quindi da un certo punto di vista tutti i numeri double sono numeri 
"decimali", nel senso che sono tutti memorizzati internamente
in un formato del tipo  0.1110101010000110001 x 2^(12), ma ovviamente
questo ha ben poco a che fare con la rappresentazione in base 10
del numero. Per esempio il numero sopra corrisponde a 3752.3828125.
C'e' poco da fare: per ottenere la parte decimale bisogna che converti
il numero in base 10, e questo e' meglio che lo lasci fare alle funzioni
preposte (siano esse in C o in VB).
In questo momento non ho tempo/voglia di farti un breve corso sulla
rappresentazione interna delle variabili intere e floating point.
Ma se cerchi sulla rete (o in libreria...) trovi sicuramente
qualcosa per chiarirti le idee.
ciao,
g.

 senza utilizzare cast o funzioni di coversione??
Eccoti un esempio funzionante (ma attento alle trappole dei
floating-point):
#include <stdio.h>
double fractional_part( double n )
{
    int i = n;
    return n - i;
}
int main()
{
    printf( "%f\n", fractional_part( 123.456789 ) );
    return 0;
}
Comunque la conversione c'è, anche se implicita. Non ti so aiutare su
come farla a livello di rappresentazione del numero.
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg

 }
credo che al posto di int bisona utilizzare long, no?
e cmq in questo modo otterresti la parte bassa dei 4 byte che formano il
double, giusto?
ma, in base a quanto detto da giovanni, non credo funzioni molto bene... o
sbaglio?


Sbagli (cioe' il programmino sopra e' giusto).
Allora, intanto tieni presente che sulla maggior parte dei compilatori C
moderni su archittetture Intel (o AMD) il tipo di dato int e il long
sono COINCIDENTI e occupano 4 bytes.
Per quanto riguarda la conversione, tieni presente che il
compilatore e' furbo, e quando tu gli converti implicitamente
o esplicitamente un double in int
(ovvero scrivendo
int i;
i = n;
oppure
int i;
i = (int) n;
e la funzione poteva anche ridursi ad un equivalente
double fractional_part( double n ){return n-(int)n;}
)
fa esattamente il calcolo che uno ragionevolmente si
aspetta, ovvero calcolare la parte intera del numero double
n e assegnarla alla variabile intera i.
Questo non si puo' fare semplicemente prendendo alcuni dei
8 bytes della rappresentazione del double, perche' come ti
ho detto i double sono rappresentati in un modo piu' complicato.
(Dai una occhiata qui, tanto per avere una idea:
http://www.na.infn.it/mfa/acust/IEEE_float.htm
 )
Ma il compilatore sa che i e n sono di tipi diversi rappresentati
in modo diverso e quindi sa cosa fare.
ciao,
g.

 double, giusto?
No, ottieni proprio la parte dopo la virgola. Perché non lo provi?


 double fractional_part( double n ){return n-(int)n;}
Infatti quella mia originale era cosě ma dato che l'OP aveva chiesto
espressamente "senza cast"... :-)


 credo che al posto di int bisona utilizzare long, no?
comunque, ripensandoci, anche i long (4 bytes, come gli int, su molte
macchine) non ti garantiscono dagli overflow.
La cosa piu' sicura, se e' disponibile sul tuo compilatore,
e' usare la funzione
double modf(double x, double *y)
definita in <math.h>
in pratica se hai
double x,y,z;
x = 123.7783;
z = modf(x, &y);
dopo la chiamata hai
z  = 0.7783 e y = 123.000000
ciao,
g.

 definita in <math.h>
Ottimo! Mi era proprio sfuggita. E deve per forza essere disponibile
dato che è standard.
