Newsgroup: it.comp.lang.c
Titolo: Problema con funzioni math

Salve a tutti, ho un piccolo problemino, mi serve una funzione che mi torni 
la parte reale di un numero con la virgola. Se faccio un cast da double a 
intero capita che numeri tipo 9.00000 mi vengano tornati come 8 cosa 
sbagliata e non voglio approssimare per eccesso e per difetto con le 
funzioni ceil e floor voglio che se ho 9.9999 e 9.00000 mi venga restituito 
sempre e solo l'intero 9. Avevo pensato di usare la funzione trunc e poi la 
funzione ceil solo che la funzione trunc mi viene detto che non c'è. In ogni 
caso c'è un modo più semplice per ottenere quello che mi serve?
Grazie, ciao ciao. 

 sempre e solo l'intero 9. 
Come ho detto sopra, questo che dici lo otterresti con un banale cast ad
int.
Il punto pero' e' che non esiste un modo, per il calcolatore,
per distinguere tra un numero 8.99999999999999464643 che tu "ti aspetti"
essere 9.000 e che quindi vuoi che ti venga troncato a 9, ed un numero
8.99999999999999464643 che tu ti aspetti essere 8.9999999 e quindi
vuoi che venga troncato a 8.
Capisci, e' un piu' un problema umano, che di C.
Quello che faccio io in casi simili e' stimare entro quali
limiti un numero double puo' avvicinarsi ad un intero senza
essere ragionevolmente identificato con esso. (Questa e' una cosa
che naturalmente dipende dal problema che sto risolvendo).
Poniamo che a tutti gli effetti per me un numero tra 8.99999 e 9
possa essere identificato con 9. Allora per ottenere la parte intera
"ragionevole" faccio una cosa del tipo
n = (int)(x+0.00001)
per i numeri tra 8 e 8.99999 mi viene comunque 8, per i numeri
tra 8.99999.. e 9.99999 mi viene 9, etc.
Quindi, se per te il semplice troncamento non va bene, prova
ad esplorare soluzioni come quella che ti ho proposto, ma che
dovrai comunque adattare in base al tuo problema, ai tuoi dati
e alle tue aspettative.
ciao,
g.

 
Buttata così:
convertila in stringa e prendi fino al punto (.)

 convertila in stringa e prendi fino al punto (.)
La conversione in stringa, per esempio attraverso sprinf,
altro non e' che un arrotondamento del numero al numero
specificato di decimali.
Quindi un numero come 5.999999999 a seconda che tu lo converta
con piu' o meno decimali potrebbe venire "stampato" come
5.9999999 oppure come 6.000.
Meglio allora fare direttamente l'operazione di
arrotondamento/troncamento in modo da decidere personalmente quando un
numero double che si avvicina ad un intero debba essere identificato con
esso o meno.
ciao,
g.

 
E già lo so...è la natura stessa dei floating-point!!
Però magari con una specifica di formato accurata per sprintf,
può darsi che non modifichi il valore nella conversione a stringa...boh!

 tra 8.99999.. e 9.99999 mi viene 9, etc.
Uhm. Io apporterei due modifiche al tuo sistema:
1. rendere meno "arbitraria" la correzione. Di fatto l' errore relativo 
su un float e' una costante dipendente dalla rappresentazione. E la 
costante e' disponibile in float.h  come FLT_EPSILON  (DBL_EPSILON per i 
double e LDBL_ESPILON per i long double);
2. la correzione che hai proposto funziona solo per x positivi. Meglio 
verificare se fabs(o fabsf o fabsl per i float e i long double)  della 
differenza tra il valore double ( o fload o long double) e' minore di 
DBL_EPSILON, FLT_EPSILON o LDBL_EPSILON).
Ancora meglio,  usare le funzioni standard (richiedono math.h) 
nearbyint, nearbyintf, nearbyintl, rint, rintf, rintl.
Giorgio

 nearbyint, nearbyintf, nearbyintl, rint, rintf, rintl.
Queste funzioni, sia pure utili, mi sembra effettuino un
arrotondamento all'intero piu' vicino
e non un "troncamento ragionato" come chiedeva l'OP.
ciao,
scusate la prolissita',
g.

 sbagliato.
Veramente la linea
n = (int)(x+0.00001)
senza ulteriori qualificazioni la hai scritta tu. Per coerenza, volendo 
sottolineare la questione dell'  errore relativo, avresti dovuto scrivere
n = (int)(x*(1+0.00001))
La riga del mio post in cui suggerivo di fare fabs della differenza era 
ugualmente fuorviante perche'  mi era saltato l'  aggettivo "relativa". 
Grazie quindi per la puntualizzazione.
Giorgio

 Grazie quindi per la puntualizzazione.
La puntualizzazione non l'ho fatta per te che sicuramente conosci la cosa,
ma per i neofiti che magari ci leggevano e che mettendo insieme il
tuo discorso (abbastanza sintetico), con il mio esempio "zoppo",
deducevano paripari che il test fabs(x-y)<=DBL_EPSILON andasse bene per testare 
l'uguaglianza dei double.
ciao,
g.