Newsgroup: it.comp.lang.c++
Titolo: Problemi di rappresentazione di numeri in Fixed Point

Per aumentare drasticamente le prestazioni di una mia applicazione grafica
ho la necessità di utilizzare dei numeri Fixed Point. Ho cercato qualche
info dalla rete e ho capito il funzionamento generale: utilizzare un long
int (32 bit) per memorizzare sia la parte intera che frazionaria e
all'occorrenza shiftare il numero per ottenere una delle due.
Ma ora sorge un problema: non riesco a rappresentare la parte frazionaria.
Nel numero 0.001 questa sarebbe 1, ma nel numero 0.1 dovrebbe essere 100???
Se dovessi seguire questa notazione (cosa peraltro non possibile) le
operazioni aritmetiche sballerebbero: 0.900 + 0.100 = 0.1000 invece di 1.0.
Qualcuno che ha già lavorato con i numeri Fixed Point o che ha qualche idea
potrebbe darmi una dritta?
Seconda domanda, riguardante il C++: le dichiarazioni friend sono
ereditarie?
Esempio: dichiaro questa classe
class Base
{
   friend MiaClasse;
   int Foo();
};
class Derived : public Base
{
};
La classe MiaClasse sarà friend di Derived? Oppure i friend vengono
ereditati a seconda che io li dichiari public, protected o private? O non
vengono ereditati affatto?
Ciao e grazie in anticipo a chi si interesserà, Giuseppe
---------------------------------------------------------------------------
_Guybrush su IRCNet canale #programmazione
---------------------------------------------------------------------------

 Nel numero 0.001 questa sarebbe 1, ma nel numero 0.1 dovrebbe essere
100???
    Puoi considerare la parte frazionaria come espressa in potenze negative
di 2, utilizzando a tal fine un numero fisso di bit. Ad esempio:
00 00 01 . 80
potrebbe essere la rappresentazione (in esadecimale) del numero:
1 + 1*2^-1 = 1.5
infatti, in binario:
00000000 00000000 00000001 . 10000000 +
00000000 00000000 00000001 . 10000000 =
------------------------------------------------------------------
00000000 00000000 00000010 . 00000000
che corrisponde a 3.
    Le operazioni di somma e sottreazione risultano elementari e
velocissime. Qualche avvertenza per la moltiplicazione: attento ad
effettuare gli opportuni shift, dopo l'operazione.
    Ciao!!!

effettuare gli opportuni shift, dopo l'operazione.
Se ho capito bene (sempre riservando 8 bit per la parte decimale) alla fine
della moltiplicazione dovrei shiftare di 8 bit verso destra. Sono sulla
buona strada?
Per quanto riguarda l'altra domanda....nessuno si fa avanti?
Ciao, Giuseppe


vengono ereditati affatto?
Lo specificatore di accesso friend è appunto uno specificatore di accesso. Nel tuo caso
questo significa che la classe MiaClasse può accedere a qualsiasi attributo / servizio
presente nella classe Base, sia esso contenuto nella sezione pubblica, sia nelle sezioni
private e protette di quest'ultima. Nota che questo non significa affatto che MiaClasse
diventi parte dell'interfaccia di Base. Infatti se scrivi qualcosa come:
#include "iostream.h"
class MiaClasse;
class Base    {
   friend MiaClasse;
public:
   int Foo() {cout << "Funzione di Base"; return 0;};
};
class MiaClasse    {
    int f1() {cout << "Funzione di MiaClasse"; return 1;}
};
int main()     {
     Base base;
     base.Foo();    // ok: Foo è parte dell'interfaccia di Base
     base.f1();        // error C2039: 'f1' : is not a member of 'Base'
}
D'altro canto, Base non può essere a conoscenza di tuttte le classi che deriverai. Base
non contiene nella sua interfaccia quelle classi (mentre è vero che queste ultime
conterranno l'interfaccia della classe base da cui derivano). Quindi non ha senso un
concetto di ereditarietà di friend.
friend è solo uno specificatore di accesso. Ancora una volta, in codice C++:
#include "iostream.h"
class MiaClasse;
class Base     {
   friend MiaClasse;
   int Foo() {cout << "Funzione di Base"; return 0;};
};
class Derived : public Base    {
   int Foo2() {cout << "Funzione di derived"; return 2;}
};
class MiaClasse    {
public:
    int f1() {    baseObj.Foo ();    // ok: MiaClasse è friend di Base
                    d.Foo();               // ok: Foo è parte dell'interfaccia (sez.
public)
                                               // di Derived
                    d.Foo2();             // ERROR!
                    return 1;
                }
private:
Base baseObj;
Derived d;
};
ERROR: error C2248: 'Foo2' : cannot access private member declared in class 'Derived'
Ciò mostra che una classe diventa friend di un'altra solo attraverso un'ESPLICITA
dichiarazione friend e che friend non si eredita, nè ha senso la distinzione tra
public/protected/private friend.
Andrea

Il tipo Currency del C++Builder della Borland funziona proprio come
descrivi: il valore e' rappresentato su un intero a 64 bit moltiplicato
per 10000. Somma e sottrazione funzionano normalmente, mentre se
moltiplichi o dividi un numero per un altro devi poi rispettivamente
dividere o moltiplicare il risultato per 10000. Parte intera e parte
frazionaria si ottengono rispettivamente con la divisione tra interi ed
il modulo. Quello che a me pare il problema piu' grave e' che per fare
calcoli utili servono rappresentazioni anche piu' grandi...
Ciao,
Nicola Musatti

public/protected/private friend.
Ti ringrazio tantissimo, sia per avermi chiarito le idee sia per avermi
spiegato in dettaglio il motivo della tua risposta.
