Newsgroup: it.comp.lang.c++
Titolo: Funzione per approssimare un numero

Esiste da qualche parte una funzione per approssimare un numero?
Ad esempio se faccio:
float a=2.78;
Come  potrei  fare ad approssimare il numero sulla prima cifra
decimale?(cioč 2.7)
E se volessi farla io, come potrebbe essere implementata?

 ha scritto nel messaggio
news:SWvO7.225694$sq5.10...@news.infostrada.it...

per troncare alla prima cifra decimale
moltiplica per 10
prendi la parte intera
dividi per 10
ritorna 2.7
altrimenti
moltiplica per 10
somma 0.5
prendi la parte intera
dividi per 10
ritorna 2.8
ciao

 ritorna 2.8
Grazie al tuo aiuto sono riuscito a implementare questa funzione:
void approssima(float& appr)
{
appr*=100;
appr+=0.5;
int temp=int(appr);
float b=temp;b/=100;
appr=b;
}
Che fa perfettamente quello che deve fare!
Solo che mi sembra poco ottimizzata.
Come potrei semplificarla nelle istruzioni?
Ciao e grazie!

Logicamente la funzione che ho fatto arrotonda alla seconda cifra
decimale...
L'ho usata per arrotondare l'euro(per ottenere i centesimi)in un
convertitore che ho scritto per
esercizio :-))

 ha scritto nel messaggio
news:4XKO7.229151$sq5.11...@news.infostrada.it...

potresti non fare i cast
#include <math.h>
float approssima (float appr)
{
    return floor(appr * 100 + 0.5) / 100 ;
}

 decimale...
beh... a sto punto farei:
#include <iostream>
int main()
{
 float a;
 float b;
 std::cout << "Inserire un numero" << std::endl;
 std::cin >> a;
 b=(static_cast<float>(static_cast<int>(a*100.0+0.5))/100.0);
 std::cout << "Il Numero approssimato e': " << b << std::endl;
}
--
Gerolamo

 b=(static_cast<float>(static_cast<int>(a*100.0+0.5))/100.0);
E stare sul semplice ?
  b = floor(a*100+0.5)/100;
Fra l'altro l'arrotondamento implicito nel cast e' ottenuto
verso lo zero, ovver "buttando" i decimali e quindi lavora
decisamente male (prova la tua formula con -3.96).
Andrea
PS:
  Le conversioni "aritmetiche" sono quelle in cui la
  sintassi di *cast<...> C++ e' secondo me oscena.
  Io uso in questi casi la sintassi float(...) che trovo
  molto piu' umana.


bah, sembra uguale alla mia.
comunque si potrebbe anche incapsulare tutto
class Euro
{
    float valore ;
public:
    Euro (float val) : valore (val)  {};
    Euro (Euro euro )  : valore (euro.valore)  {}
 /* operatore di assegnazione */
    Euro & operator = (Euro );
 /* operatori aritmetici */
    friend Euro & operator + (Euro a, Euro b);
    friend Euro & operator - (Euro a, Euro b);
    ....
    ....
 /* cast */
    operator float () {
        return floor(valore * 100+0.5) / 100  ;
    }
};
e la potrei usare come
Euro e = 7.4578 ;
cout << e ;    // cout << (float) e
scriverebbe 7.46
Addirittura si potrebbe pensare ad una classe genitrice
class Valuta ;
da cui deriviare la classe Euro (usa due decimali) o classe Lira (non usa
decimali)
ciao

decimali)
I nomi non mi sembrano appropriati... al limite le classi
dovrebbero chiamarsi ImportoInLire, ImportoInEuro e 
ImportoInValuta. Fra l'altro credo che nel caso di Euro
(e dollari) sia molto piu' sano utilizzare numeri interi
di centesimi come rappresentazione (0.01 e' un numero
periodico se espresso in binario e quindi non puo' essere
rappresentato correttamente da un float; credo che usare
float in questi casi sia volersi cercare a tutti i costi
problemi di quadratura).
Andrea


no, i nomi sono appropriati, Euro, Lira, Dollaro sono già degli importi (si
dice "ho 100 lire", non "ho l'importo di 100 lire").
Per la rappresentazione con float penso che potrebbe essere corretta, perchè
in questo caso quello che pensavo è una classe che permettesse di fare i
conti con numeri reali, e avere solo la visualizzazione con i decimali.
Per esempio
Euro a, b = 3.45988, c = 6.758977 ;
a = b + c ;    // a.valore = 3.45988 + 6.758977
float d = float(b) + float(c) ;    // d = 3.46 + 6.76
ciao
sergio

conti con numeri reali, e avere solo la visualizzazione con i decimali.
A me continua a non piacere. Anche una conversione implicita
che arrotonda e' "pericolosa". Le conversioni implicite sono
delle armi a doppio taglio: comodita' perche' si attivano
quando necessarie e senza dover essere chiamate contro
sorprese perche' ogni tanto si attivano a sproposito.
Un campanello di allarme che di solito si considera e'
questo: se la conversione "perde" qualcosa per strada
allora la conversione implicita probabilmente non e' la
cosa logicamente corretta in quel contesto.
Es: conversione implicita int->double = no problem;
conversione implicita double->int = rischio.
Si tratta ovviamente di regole "morbide", ad esempio si
considera spesso int->float una conversione implicita
plausibile anche se in realta' su molte piattaforme
sia int che float sono a 4 byte e quindi e' evidente
che non e' possibile mappare gli interi sui float
senza perdere in alcuni casi qualcosa.
Andrea

 float d = float(b) + float(c) ;    // d = 3.46 + 6.76
Spero che il tuo sia un programma "giocattolo" e non un'applicazione
seria. Il sistema binario permette di rappresentare un numero molto
limitato di numeri razionali in rapporto al numero di cifre utilizzate
per la parte frazionaria:
binario	decimale
0	= 0
	  0,1
	  0,2
	  0,3
	  0,4
0,1	= 0,5
	  0,6
	  0,7
	  0,8
	  0,9
1	= 1
Questo vuol dire che la maggior parte dei valori che utilizzerai sara'
arrotondato in modo inaccettabile (cambieranno anche i centesimi).
Normalmente per fare conti in denaro si utilizzano valori interi che
rappresentano il grado di precisione che si vuole garantire. Ad esempio
io rappresento i valori in Euro moltiplicati per 10000, in modo da
"coprire" con due cifre decimali aggiuntive eventuali arrotondamenti che
potrebbero impattare sui centesimi.
Un'alternativa che sto valutando e' l'utilizzo di tipi floating point,
ai quali applico comunque lo stesso meccanismo. Se la mantissa e'
sufficientemente grande da rappresentare esattamente i valori che
utilizzo normalmente, lo standard IEEE garantisce che i risultati dei
miei conti sono esatti, e nei casi eccezionali in cui dovessi utilizzare
valori piu' grandi, i tipi floating point mi garantiscono un degrado di
precisione piuttosto che un overflow come con i tipi interi.
Ciao,
Nicola

dice "ho 100 lire", non "ho l'importo di 100 lire").
Euro, Lira, Dollaro sono delle unita' di misura, non degli
importi.  L'importo e' la grandezza.