me lo puoi postare così evito perdite di tempo inutili perfavore?
me lo puoi postare così evito perdite di tempo inutili perfavore?
visitate www.linkutility.it !!! Il sito per ogni necessità
NSString *test1 = [NSString stringWithFormat:@"%.16f", d1];
giusto? Per le operazioni sulle stringhe mi sapresti indicare una pagina web o guida che illustra bene o quasi tutto ciò che devo sapere?
Grazie mille per l'interessamento![]()
visitate www.linkutility.it !!! Il sito per ogni necessità
La domanda che fai in realtà non ha una soluzione "vera" per un motivo molto semplice: nel momento in cui memorizzi un numero decimale in un double la partita è persa, non puoi più dire esattamente dove terminava il numero "originale".
Prova a stampare 0.1 a 100 cifre decimali (usando ad esempio printf("%.100f", 0.1)): l'output sarà del tipo
Questo accade perché i double memorizzano i numeri in binario, e molti numeri razionali che hanno un'espansione decimale finita (come ad esempio 0.1) in binario sono numeri periodici (0.1dec = 0.00011001100110011(0011)... bin). I double ovviamente hanno una mantissa finita (di 53 bit), per cui il numero in questione viene arrotondato alla 53esima cifra dopo la virgola, producendo un risultato inaccurato.codice:0.1000000000000000055511151231257827021181583404541015625000000000000000000000000000000000000000000000
Ora, data questa intrinseca imprecisione come può sapere la printf nel momento in cui le passi un certo numero se tu intendevi precisamente quel numero lì, oppure se quello che vede è il risultato di un arrotondamento di un numero decimale? Ovvero, come fa a dire "in 0.1 le cifre finiscono lì, non serve stampare altro" se in realtà il numero che riceve lei va avanti per altre 30 cifre decimali che non sono zeri?
Per questo motivo, printf, se non viene fornito alcuno specificatore di numero di cifre decimali, arrotonda sulla sesta cifra decimale, dato che viene presa come riferimento la precisione di un float, che è di circa 7 cifre decimali (ha 24 bit di mantissa, per cui log10(2^-24)=-7,22); stampare cifre oltre questa precisione per un float corrisponde a stampare fuffa, e analogamente stampare oltre 15 cifre decimali per un double.
Il problema di %.<precisione>f è che, se gli specifichi un numero di cifre decimali da stampare, provvede a stamparle tutte anche se sono zeri (a differenza di %f "naturale", che arrotonda a 6 cifre ma ne stampa meno se possibile).
Fondamentalmente, ci sono due soluzioni semplici:
- usare %g; %g consente di specificare la precisione massima da impiegare, per cui se usi "%.12g" (precisione massima sensata da usare per dei double) arrotonderà alla 12esima cifra decimale, non stampando gli zeri finali se non sono seguiti da alcuna cifra diversa da zero; il problema di %g è che in "determinate" circostanze (se il numero è troppo grosso o troppo piccolo) può passare alla rappresentazione esponenziale, il che può non essere sempre desiderato;
- usare %.15f con sprintf (o analoghe funzioni Objective C, stringWithFormat segue in gran parte le specifiche printf salvo qualche aggiunta) per stampare il numero all'interno di una stringa (come ti è stato suggerito), quindi scorrere la stringa da destra verso sinistra uccidendo tutti i caratteri finché non si incontra qualcosa di diverso da zero.
Amaro C++, il gusto pieno dell'undefined behavior.
Grazie MItaly per la tua spiegazione!comunque fmeggysax appena torno a casa scrivo la funzione che potresti usare e te la posto allora
Per le pagine web peró non ti so dire molto siccome a me piace da sempre il c++ e quindi con il c ho solo imparato le basi e qualcosa di più avanzato ma le funzioni non me le ricordo bene... Comunque una veloce ricera del tipo : "string c" dovrebbe fornirti i risultati da te desiderati.
Ultima modifica di maluz1; 23-11-2013 a 08:17
Concordo con maluz1! Grande Mitalyquando torno a casa provo con %g altrimenti aspetto maluz1 che mi aiuta con quel codice :3
visitate www.linkutility.it !!! Il sito per ogni necessità
ciao fmeggysax, oggi ho implementato il codice usando il c e mi sono quasi fuso il cervello. all'inizio andava praticamente alla perfezione fino a quando ottenevo risultati errati in alcuni casi: così ho riscritto la funzione pow della math.h e tutto andava correttamente fino a quando un'altra eccezione si è verificata: con 0.123 veniva perfetto, con 0.234 una roba illeggibile. così ho riscritto anche la trunc ma sostituendo non so perchè ma non risultava. questa sarà la mia ultima esperienza con il c!
a parte gli scherzi il codice te lo posto ma riguardatelo soprattutto con le conversioni:
lavoraci un pò, scusami per averti illuso anche se poi alla fine il codice è quello... almeno la logica è quellacodice:#include <stdio.h> #include <math.h> int new_trunc( double n ) { int x= 0; while( ( n > x ) && ( n > x + 1) ) x++; return x; } int new_pow( int base, int esp ) { int pot= 1; int i; for ( i= 0; i < esp; i++ ) pot*= base; return pot; } char* double_to_str( double p_dec, char* str ) { int p_dec_int= 0; int i= 0; int n_dec= 0; // numero cifre decimali int div; while( p_dec != trunc( p_dec ) ) { // lo rendo senza virgola p_dec*= 10; n_dec++; } p_dec_int= p_dec; n_dec--; while( n_dec >= 0 ) //memorizzo in str le singole cifre trasformandole da int a carattere ascii div= new_pow( 10, n_dec ); if ( n_dec == 0 ) div= 1; str[i]= (char) ( p_dec_int/div + 48 ); p_dec_int= p_dec_int - ( ( p_dec_int / div ) * div ); n_dec--; i++; } return str; } main() { const int DIM_DEC_DOUBLE= 16; // qui ci metti il limite di cifre che vuoi controllare( per eliminare gli 0 ) int i; double n; int p_int; double p_dec; char s[DIM_DEC_DOUBLE]; for( i= 0; i < DIM_DEC_DOUBLE; i++ ) //inizializzo il vettore s[i]= ' '; scanf("%lf", &n ); p_int= trunc( n ); // parte intera del numero p_dec= n - p_int; // parte decimale del numero printf("%d,%s\n", p_int, double_to_str( p_dec, s ) ); }ciao!
Mi sembra che tu ti sia complicato un po' la vita inutilmente, oltre al fatto che ad occhio non gestisci correttamente un paio di corner case... il problema comunque si può risolvere in maniera relativamente semplice delegando il grosso del lavoro alla printf:
La parte vagamente ingarbugliata è la questione della malloc (per gestire il caso in cui la stringa sia più lunga del buffer allocato localmente), ma per il resto è abbastanza semplice capire come funziona.codice:int fprintdouble(FILE *stream, double num, unsigned int maxPrecision) { char buf[16]; char *bufPtr=buf, *ptr; int len=snprintf(buf, sizeof(buf), "%.*f", maxPrecision, num); if(len<=0) return len; else if(len>=sizeof(buf)) { bufPtr=malloc(len+1); if(bufPtr==NULL) return -1; snprintf(bufPtr, len+1, "%.*f", maxPrecision, num); } for(ptr=bufPtr+len-1; ptr>=bufPtr && *ptr=='0'; ptr--) *ptr='\0'; if(*ptr=='.') *ptr='\0'; fputs(bufPtr, stream); if(buf!=bufPtr) free(bufPtr); return len; } int printdouble(double num, unsigned int maxPrecision) { fprintdouble(stdout, num, maxPrecision); }
Ultima modifica di MItaly; 24-11-2013 a 16:48
Amaro C++, il gusto pieno dell'undefined behavior.
D: ma a me serve per object c proprio perché non lo conosco bene... mentre c e java gli conosco comunque grazie mille![]()
visitate www.linkutility.it !!! Il sito per ogni necessità
Wow... Mitaly io non avrei mai fatto un codice del generebe complimenti...!