Newsgroup: it.comp.lang.c++
Titolo: Arrotondare un double...

Ciao a tutti,
qualcuno sa dirmi se e come è possibile arrotondare un double di n cifre
decimali ad un numero di cifre decimali definito?
esiste una round?
Ex
round( 5,1234321321421)=5,12
Grazie.

 decimali ad un numero di cifre decimali definito?
int(5,12345678*100)/100.0
= 5,12.
int(5,12345678*10000)/10000.0
= 5,1234
Ecc...
Farsi una funzioncina è facile...
-- 
Luc.

 wrote in message
news:MPG.17f0f0102...@tornado.fastwebnet.it...


 valore che alla 15,16 esima cifra decimale si fa i cavoli suoi?
Il rischio c'è sempre, anche prima della 15 cifra se non ricordo male... 
Prova! 
-- 
Luc.

 valore che alla 15,16 esima cifra decimale si fa i cavoli suoi?
Sei quasi sicuro di non ottenere un valore esatto, perche' solo una
piccola parte dei numeri decimali e' rappresentabile in binario.
Ciao,
Nicola

 
Sě, lo moltiplichi per 100, lo trasformi in un intero e poi lo
ridividi per 100!
ad esempio:
double round(double value)   {
   long const temp = long(value * 100);
   return double(value) / 100.0;
}
potresti parametrizzare anche il valore volendo... purtroppo funziona
se value non assume valori troppo grandi, altrimenti sfora. Al momento
perň non mi viene in mente altro.

 decimali ad un numero di cifre decimali definito?
ma lo devi solo stampare o usare per fare confronti?
se lo devi solo stampare, i metodi di cout ti possono essere utili
cout << setprecision(7) << setiosflags(ios::showpoint | ios::fixed):
se invece devi fare dei confronti, allora non ha senso l'arrotondamento, in
quanto il risultato sarà sempre un numero in virgola mobile.
L'unica cosa abbastanza sicura che puoi fare, è usare la variabile
FLT_EPSILON[1] e fare il confronto su questa, ad esempio due numeri in
virgola mobile sono diversi se:
abs(x-y) > FLT_EPSILON
etc.
etc.
Cioè. la loro differenza deve essere maggiore di FLT_EPSILON
Spero di esserti stato d'aiuto.
[1] FLT_EPSILON è il più piccolo numero tale che (x + FLT_EPSILON) è diverso
da x.
--
Ciao.
Maurizio
P.S.: eliminare _!NO$PAM! per rispodere in privato

"Maurizio Penna" ha scritto nel messaggio
:
: > qualcuno sa dirmi se e come è possibile arrotondare un double di n cifre
: > decimali ad un numero di cifre decimali definito?
:
: ma lo devi solo stampare o usare per fare confronti?
:
: se lo devi solo stampare, i metodi di cout ti possono essere utili
:
: cout << setprecision(7) << setiosflags(ios::showpoint | ios::fixed):
:
: se invece devi fare dei confronti, allora non ha senso l'arrotondamento,
in
: quanto il risultato sarà sempre un numero in virgola mobile.
Potrebbe avere senso se vuole fare delle somme. Supponi di dovere sommare
dei prezzi a cui viene applicato uno sconto.
Sconti ciascun prezzo, lo arrotondi/tronchi al centesimo e infine
li sommi.
Il risultato potrebbe essere diverso se non arrotondi/tronchi o lo fai
solo alla fine.
...
:
:
:
: [1] FLT_EPSILON è il più piccolo numero tale che (x + FLT_EPSILON) è
diverso
: da x.
A memoria, e logica, io direi che FLT_EPSILON rappresenta il numero piu`
piccolo per cui float(1.0 + FLT_EPSILON) != float(1.0).
#include <iostream>
#include <climits>
int main(int argc, char* argv[])
{
  using namespace std;
  cout << (float(1.0 + FLT_EPSILON) != float(1.0)) << endl;
  cout << (float(10.0 + FLT_EPSILON) != float(10.0)) << endl;
  return 0;
}
ciao
Massimo

 piccolo per cui float(1.0 + FLT_EPSILON) != float(1.0).
esatto.
Ciao,
Nicola

double round(double num, int p)             // num è il double da
arrotondare e p il numero di cifre dopo la virgola
{
    int mult=(int) (num*(10.0f^(p+1)));     // Setta il numero di cifre dopo
la virgola + una per la precisione
    mult=mult+5;                                      // Arrotonda il numero
    mult=mult/10                                      //
    return (  (double)(mult)  ) /(10.0f^p);  // Ritorna il numero che ti
serve
}

"Nicola Musatti" ha scritto
:
: Trattare somme in denaro con tipi di dato in virgola mobile e' un buon
: modo per cercarsi dei guai, e non solo computeristici. Per avere i
: risultati esatti normalmente richiesti in questo tipo di applicazioni e'
: opportuno utilizzare classi che implementano numeri decimali in virgola
: fissa (ad esempio il Currency della Borland).
:
Il Currency non lo conosco, ma concordo. Tra cio` che passa lo std i
double rappresentano il meno peggio. Bisogna conoscere i limiti dei
double e delle somme usabili, in qualche caso ci si puo` accontentare.
Il mio esempio era solo per dimostrare che ci sono casi in cui si puo`
volere arrotondare.
: > : [1] FLT_EPSILON è il più piccolo numero tale che (x + FLT_EPSILON) è
: > diverso
: > : da x.
: >
: > A memoria, e logica, io direi che FLT_EPSILON rappresenta il numero piu`
: > piccolo per cui float(1.0 + FLT_EPSILON) != float(1.0).
:
: esatto.
:
Meglio: il piu` piccolo numero positivo, rappresentabile con un float,
per cui ...
ciao
Massimo

 per cui ...
No, e' proprio come e' definito sopra e non e' la stessa cosa. Se i
float sono rappresentati in modo normalizzato su 32 bit con 1 di segno,
8 di esponente e 23 di mantissa avremo presumibilmente (mantissa in
binario ed esponente in decimale):
1f          =  + 0,10000000000000000000000 e 2
FLT_EPSILON =  + 0,00000000000000000000001 e 2
min positivo = + 0,00000000000000000000001 e -127
Ciao,
Nicola

"Nicola Musatti" ha scritto 
: > 
: > Meglio: il piu` piccolo numero positivo, rappresentabile con un float,
: > per cui ...
: 
: No, e' proprio come e' definito sopra e non e' la stessa cosa. Se i
: float sono rappresentati in modo normalizzato su 32 bit con 1 di segno,
: 8 di esponente e 23 di mantissa avremo presumibilmente (mantissa in
: binario ed esponente in decimale):
: 
: 1f          =  + 0,10000000000000000000000 e 2
: FLT_EPSILON =  + 0,00000000000000000000001 e 2
: min positivo = + 0,00000000000000000000001 e -127
: 
Quello che intendo io e` che qualunque numero negativo abbastanza
grande sarebbe tale per cui, per esempio:
1.0f + -1.0f != 1.0f 
e
-1.0f piu` piccolo di FLT_EPSILON
ciao
Massimo

 -1.0f piu` piccolo di FLT_EPSILON
Ok. Non avevo capito chiaramente cosa tu inntendessi.
Ciao,
Nicola

 double rappresentano il meno peggio. 
puo` essere, ma usare i double per rappresentare somme di denare porta 
inevitabilmente a dei bug; molto meglio fare qualcosa di questo genere 
(non testato):
int pow(int base, int exp) {
        if (exp<0) throw std::out_of_range("Esponente negativo");
        if (exp==0) return 1;
        int res = 1;
        for(int i=0; i<exp; i++)
                res *= base;
        return res;
}
template<int decimal>
class FixedPoint {
        long val;
public:
        FixedPoint(double d): val( (int)d * pow(10,decimal) ) { }
        operator double() const { return (double)val/ pow(10, decimal); }
};
ovviamente si dovrebbe aggiungere anche il supporto per operazioni e 
conversione tra FixedPoint con precisione diversa, pero` come punto di 
partenza dovrebbe andare bene.
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

 partenza dovrebbe andare bene.
già. Però c'è il problema che se (int)d * pow(10, decimal) raggiunge
la dimensione massima il valore è completamente errato (errore
presente anche nella versione che ho postato io). Ci ho pensato un po'
e mi è venuto in mente questo:
double ipart = 0;
double const fpart = modf (somma, &ipart);
// la parte frazionaria è in fpart.
e poi fare quello che hai fatto tu solo sulla parte frazionaria (in
questo caso non dovrebbe essere possibile sfondare il long o,
perlomeno, è molto più difficile).
Il numero poi può essere ricostruito facendo una semplice somma di
ipart e del vaore trasformato di fpart.

 };
Hai solo il problema che il long non è infinito, quindi se uno vuole 5 
decimali significativi ti troveresti un po' a "corto" di cifre...
Ne approfitto per fare una domanda: qualcosa di simile c'è già 
implementato in qualche libreria free, magari con tipi numerici a 
dimensione illimitata?
-- 
Andrea Bergia - studente
Linux Registred User #281550

         FixedPoint(double d): val( (int)d * pow(10,decimal) ) { }
ecco, mi sono accorto adesso di un bel bug: ovviamente il cast ad int va 
fatto *dopo* aver moltiplicato per la potenza di 10:
        (int)(d*pow(10,decimal))


 dimensione illimitata?
Su Boost qualcosa del genere probabilmente c'e', anche se non ancora nel
rilascio ufficiale.
Ciao,
Nicola