PDA

Visualizza la versione completa : [C++] Accertare se valore stringa supera limiti di tipo numerico


arasino
06-06-2012, 02:59
Salve come faccio a sapere se un double o un float scritto come stringa rispetta i limiti?

Ho provato a fare in questo modo ma il min non dovrebbe avere segno negativo?



#define LIMITE_FLOAT_MIN numeric_limits<float>::min() //1.17549e-38
#define LIMITE_FLOAT_MAX numeric_limits<float>::max() //3.40282e+38
#define LIMITE_DOPPIO_MIN numeric_limits<double>::min() //2.22507e-308
#define LIMITE_DOPPIO_MAX numeric_limits<double>::max() //1.79769e+308

int main(int argc, char * argv[])
{
string numero = "1.79769e+308";

double val = atof(numero.c_str());

if((val<LIMITE_DOPPIO_MIN) || (val>LIMITE_DOPPIO_MAX))
{
//errore fuori limite
}

return 0;
}


Volevo sapere anche se è molto difficile avere un limite come fa java dove i suoi tipi non dipendono dal sistema in uso.

grazie

Who am I
06-06-2012, 16:14
Eccetto casi rari, i floating point a singola precisione hanno 4 byte, quelli a doppia precisione hanno 8 byte.

float:
23 bit per la mantissa, 8 per l' esponente, 1 per il segno
Si ottiene il numero così: (1.0+mantissa)*2^(esponente-127)*2^(segno)
Quindi il più grande numero ottenibile è 1.999*2^127
Quindi circa 3.4e38

double:
ha 52 bit per la mantissa, 11 bit per l' esponente, 1 bit per il segno
Valore: (1.0+mantissa)*2^(esponente-1023)*2^(segno)
Quindi circa 1.79e308

Controlla se hai i double di 8 byte e i float di 4 byte.Se è così puoi usare questi calcoli.
Se non è così puoi reperirli in float.h, dove:
- FLT_MAX è il più grande valore che può avere un floating point a singola precisione;
- DBL_MAX è il più grande valore che può avere un floating point a doppia precisione;

MItaly
06-06-2012, 16:50
Non ha senso verificare se il valore restituito da atof sta in un double: dato che atof restituisce un double, come potrebbe questo valore essere più grande del range del double? :madai!?:

Sarebbe piuttosto compito della funzione di conversione (atof) riportare un errore se il valore fornito è troppo grande per i double; purtroppo atof non restituisce alcun errore, dovresti usare invece strtod, che restituisce valori appropriati in caso si forniscano valori troppo grandi o troppo piccoli.

In ogni caso, in C++ dovresti usare direttamente gli stream, estrarre un valore double e verificare se il failbit risulta impostato dopo l'operazione.

oregon
06-06-2012, 16:53
Originariamente inviato da MItaly
come potrebbe questo valore essere più grande del range del double? :madai!?:

:bhò:

arasino
06-06-2012, 21:19
Originariamente inviato da MItaly
Non ha senso verificare se il valore restituito da atof sta in un double: dato che atof restituisce un double, come potrebbe questo valore essere più grande del range del double? :madai!?:


nel caso il valore superasse il range, atof mi restituisce inf che è appunto maggiore.
comunque sia questo discorso va bene solo con il float.

arasino
06-06-2012, 21:31
Originariamente inviato da Who am I
Eccetto casi rari, i floating point a singola precisione hanno 4 byte, quelli a doppia precisione hanno 8 byte.


leggendo il paragrafo Differenze con il C++ a questo link (http://it.wikibooks.org/wiki/Java/Tipi_di_dato) dice che java stabilisce il limite minimo e il limite massimo dei valori ammessi dai tipi numerici.Si può fare anche con il c++?



Originariamente inviato da MItaly
In ogni caso, in C++ dovresti usare direttamente gli stream, estrarre un valore double e verificare se il failbit risulta impostato dopo l'operazione.


in questo modo?



string ConvertiDoubleStringa(double numero)
{
string valore;
ostringstream oss;
oss << numero;
valore = oss.str();
return valore;
}

double ConvertiStringaDouble(string numero)
{
double valore;
istringstream myStream(numero);
myStream>>valore;
return valore;
}

MItaly
06-06-2012, 21:33
Originariamente inviato da arasino
nel caso il valore superasse il range, atof mi restituisce inf che è appunto maggiore.
comunque sia questo discorso va bene solo con il float.
In effetti hai ragione. :mem: Comunque ti sconsiglio di usare le #define in quella maniera (piuttosto usa un const double), e in generale di usare la atof per quanto detto sopra.

Per quanto riguarda la numeric_limits<double>::min(), si riferisce al valore più piccolo (in valore assoluto) diverso da zero che può essere rappresentato; per ottenere invece il limite inferiore del range dei double ti basta prendere -numeric_limits<double>::max().

MItaly
06-06-2012, 21:36
Originariamente inviato da arasino
leggendo il paragrafo Differenze con il C++ a questo link (http://it.wikibooks.org/wiki/Java/Tipi_di_dato) dice che java stabilisce il limite minimo e il limite massimo dei valori ammessi dai tipi numerici.Si può fare anche con il c++?

C++ non stabilisce i minimi e i massimi dei tipi per consentire alle varie piattaforme di usare interi/float delle dimensioni "naturali" della macchina. Definisce però il range minimo garantito per ogni tipo.
Tieni comunque conto che i tipi in virgola mobile alla fine sono gli stessi ovunque (salvo piattaforme esoteriche).


in questo modo?



string ConvertiDoubleStringa(double numero)
{
string valore;
ostringstream oss;
oss << numero;
valore = oss.str();
return valore;
}

double ConvertiStringaDouble(string numero)
{
double valore;
istringstream myStream(numero);
myStream>>valore;
return valore;
}

Si può fare così, eventualmente controllando lo stato dello stream dopo l'operazione di estrazione per verificare se è andata a buon fine.

arasino
06-06-2012, 21:40
Originariamente inviato da MItaly
C++ non stabilisce i minimi e i massimi dei tipi per consentire alle varie piattaforme di usare interi/float delle dimensioni "naturali" della macchina. Definisce però il range minimo garantito per ogni tipo.
Tieni comunque conto che i tipi in virgola mobile alla fine sono gli stessi ovunque (salvo piattaforme esoteriche).

Quindi java utilizza il range minimo garantito per ogni tipo?

grazie ancora.

MItaly
06-06-2012, 22:01
Originariamente inviato da arasino
Quindi java utilizza il range minimo garantito per ogni tipo?

No, Java garantisce un range esatto per ogni tipo; int, ad esempio, è garantito che sia un intero a 32 bit in aritmetica a complemento a 2. Da un lato guadagni in portabilità dei programmi (che lavorano con gli stessi tipi dovunque vengano eseguiti), dall'altro però può essere una limitazione (su una macchina con processore a 16 bit lavorare con gli interi a 32 bit è lento). Per Java questo non è un problema (processori embedded low-end o architetture molto esoteriche non sono tra i target di Java), mentre per C e C++ è importante poter lavorare in maniera efficiente su qualunque architettura.

Loading