Newsgroup: it.comp.lang.c++
Titolo: Quesito: come rappresentereste il denaro?

Ciao a tutti,
seguendo il mio stesso invito, ecco un quesito per ravvivare la
discussione.
In un'applicazione finanziaria il denaro assume in un certo senso due
forme: la prima, che potremmo chiamare "denaro effettivo", riguarda
operazioni realmente compiute; si sommano le entrate, si sottraggono le
uscite, e cosi' via. Questa forma e' caratterizzata dall'esigenza di
precisione assoluta, se il cliente ti ha dato 1000 euro non puoi dirgli
che te ne ha dati 999,99 . Le operazioni usate piu' comunemente in
questo caso sono addizione e sottrazione.
La seconda forma, che potremmo chiamare "denaro potenziale", riguarda
invece di solito cio' che potrebbe succedere al denaro, come per
esempio l'applicazione di tassi di rendimento. Questa forma richiede la
massima accuratezza nei calcoli ed in genere coinvolge moltiplicazione
e divisione, nonche' spesso calcoli di una certa complessita'.
Come rappresentereste il denaro a fronte di questi requisiti? Mi rendo
conto che questa non e' una domanda di C++ in senso stretto, bensi' di
disegno in senso piu' astratto. Il mio obiettivo pero' e' arrivare alla
fine ad una implementazione in C++ e sono convinto che la scelta del
linguaggio possa avere un'influenza notevole sulle possibili soluzioni.
Vi suggerirei pero' di evitare almeno per il momento di buttarvi a
scrivere codice all'impazzata, concentrandovi sulle possibili tecniche
per risolvere il problema da un punto di vista piu' astratto. Se la
discussione prende slancio in seguito affronteremo anche il problema
delle soluzioni concrete.
Ciao,
Nicola
P.S. James, se stai leggendo, magari aspetta un giorno o due prima di
inviare la tua risposta, in modo che persone meno esperte non siano
intimidite dalla tua competenza.

 Come rappresentereste il denaro a fronte di questi requisiti?
Il quesito č molto interessante e penso che valga la pena 
discuterne in questo gruppo se si arriva, poi, ad 
un'implementazione utile, in C++.
Prometto di pensarci meglio, ma dimmi, č lecito partire dall'idea 
che la rappresentazione del "denaro potenziale", essendo il frutto 
di moltiplicazioni e divisioni (operazioni imprecise, per un 
computer), debba basarsi, il piů possibile, su informazioni 
precise?  Mi spiego: sapendo di dover moltiplicare un importo per 
il 25%, č meglio conservare l'informazione 1/4 che non 0,25 ?
Per me l'argomento č nuovo, quindi posso dire cazzate :-)

Nicola Musatti wrote:

secondo me il quesito è molto interessante, però non sono affatto 
d'accordo con il trattenersi dallo scrivere codice. Per rendere il tutto 
più IT con il newsgroup, si potrebbe partire da dei test case reali in 
c++. Ad esempio (adotto la sintassi di cxxtest, ma il senso dovrebbe 
essere chiaro):
class MoneyTest: public CxxTest::TestSuite
{
    void testAddizione() {
       Money five(5, "EUR");
       Money ten(10, "EUR");
       const Money fifteen(15, "EUR");
       TS_ASSERT_EQUALS(fifteen, five + ten);
    }
};
e da qui' procedere. Che ne pensate?
-- 
MSN: sirpsycho_78 -at- hotmail dot com
"Arditi, com'altro nomare questi baldi fiori del regime che osarono 
porre un imperativo categorico tra le sabbie bolsceviche di Marte."

 disegno in senso piu' astratto.
Ciao Nicola, mi rendo conto che mi esporrň ad insulti di qualsiasi tipo 
(ma forse me li merito dato che probabilmente non ho capito la 
domanda...), ma... cos'hanno i double che non vanno?
Per la questione dei 999.99 i double hanno una precisione ben superiore 
alle due cifre decimali quindi potrai benissimo arrotondare il risultato 
  finale delle tue somme diciamo a +/. 0.005 (gli "euri" comunemente si 
contano ai centesimi).
Io in effetti ho un'altro tipo di esperienza... ma con i double nei miei 
programmi di calcolo scientifico ottengo delle precisioni che soddisfano 
  anche il fisico piů esigente.
Ma la risposta č talmente banale che sicuramente non ho considerato 
diverse cose... ciao.

 [...]cos'hanno i double che non vanno?
I double non rappresentano in modo preciso, è questo il problema.
Nessuno sano di mente userebbe i double per rappresentare il 
denaro e chi lo fa si trova, prima o poi, problemi di round off...
In Delphi, ad esempio, esiste il tipo Currency, che è in realtà un 
intero a 64 bit, benché possa essere usato per le diverse 
operazioni come un double.

Andrea Laforgia ha scritto:

Immaginavo... infatti io non faccio programmi che calcolano denaro... ma 
  forze, pressioni velocità e altre grandezze che non dividono le 
persone come fa il denaro... nei miei casi la precisione è comunqe più 
che soddisfacente e arrivo tranquillamente a diverse cifre dopo la 
virgola e i calcoli sono realmente molto complessi (differenze finite e 
altre diavolerie)...
Vabbè... ci ho provato... comunque la vostra discussione si fa 
interessante... molto più delle ultime fatte in questo NG.
ciao e grazie per le tue spiegazioni.

 e divisione, nonche' spesso calcoli di una certa complessita'.
Cerca di lavorare in intero fino quasi alla fine; o usa numeri
razionali (rapporti tra due interi) per cui esistono tante classi gia'
belle che pronte.  O usa classi ad hoc tipo "unlimited precision
integers" tipo quelli GNU della (credo) gmp (che non ho mai usato).
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy              ROT13: 
ybe...@cq.vasa.vg

 razionali (rapporti tra due interi)[...]
Concordo.

per risolvere il problema da un punto di vista piu' astratto. 
Forse sono andato troppo sul concreto...
Saluti  Manlio Perillo

 Volendo si possono anche usare i numeri a virgola mobile[...]
Questa soluzione è da scartare.


In realta', volendo approfondire il discorso, le soluzioni che ho
proposto si basano sulla definizione di un tipo numerico 'esterno' che
supporta le operazioni numeriche di cui abbiamo bisogno e nel modo in
cui abbiamo bisogno.
Per il caso specifico di valuta monetaria si potrebbero usare
semplicemente gli interi; ad esempio 10,99 euro sono, in realta', 1099
centesimi.
P.S.
Come mai Boost non supporta un tipo Decimal o Currency?
Saluti  Manlio Perillo

 centesimi.
Ok, il problema, però è quando compi delle divisioni o 
moltiplicazioni.  Ad esempio, se devi calcolare un tasso 
d'interesse, magari applichi il 13,43% all'importo di partenza 
(supponiamo 102,37 euro).
Pur ammettendo di rappresentare l'importo con un intero (es.: 
102,3700 -> 1023700), la divisione comporta una perdita di 
precisione.
Probabilmente, converrebbe considerare la moltiplicazione per una 
frazione: 102,37*13,43% = 102,37*13,43/100, quindi l'importo in 
denaro sarebbe bene memorizzarlo come numero razionale N/D:
N=1023700*1343    = 137482910000
D=100*10000*10000 =  10000000000
Se è possibile, si semplifica:
N=13748291 0000 -> N = 13748291
D= 1000000 0000 -> D = 1000000
In questo modo memorizzi, comunque, l'importo esatto, senza 
arrotondamenti.  Sarà poi il sistema di rappresentazione che 
perderà cifre, ma l'importo conservato in memoria è comunque 
esatto.  Non so se ho spiegato il concetto ;-)

 N=1023700*1343    = 137482910000
Scusa, ovviamente è
N=1023700*134300


Non credo si possa parlare di perdita di precisione.
Del resto alla fine comunque la cifra si arrotonda
(ma non so i dettagli sul come, magari Nicola puo' dirci di piu').
L'euro, ad esempio, si conta solo fino ai centesimi.
Dato che, secondo l'IEEE 754, le varie operazioni (moltiplicazione,
divisaione, somma, differenza e radice quadrata) arrotondano in modo
esatto, dovrebbe bastare semplicemente convertire dividendo e divisore
in float, applicare le regole per l'arrotondamento e riconvertire in
intero.
Per maggiori informazioni:
http://docs.sun.com/source/806-3568/ncg_goldberg.html
Nel tuo esempio (supponendo di usare l'euro):
102,37 -> 10237
quindi il tasso di interesse e':
10237 * 1343 / 100 / 100 -> 1374,8 ->(??) 1375
(ma magari si puo' direttamente moltiplicare per 13.43, qui sto
supponendo di seguire la stessa convenzione anche con i numeri
normali, non solo con le valute)
infine la somma finale:
10237 + 1375 = 11612 -> 116.12
Saluti  Manlio Perillo

 esatto,
Stai inquadrando il problema sbagliato.  Il problema non è 
l'esattezza dell'arrotondamento, ma la propagazione dell'errore 
nei calcoli.  Eseguire calcoli tra numeri già approssimati 
amplifica l'errore di arrotondamento finale.  Questo, quando si ha 
a che fare con il denaro (ma non solo, se l'errore è grande) può 
essere pericoloso.
Usare numeri rappresentati secondo lo standard IEEE 754 o comunque 
standard studiati per la virgola mobile, per rappresentare il 
denaro, non è corretto.
In determinati linguaggi (se non erro inclusi SmallTalk, Ada, 
Fortran e COBOL) il denaro è rappresentato da interi.  Lo stesso 
vale in Delphi, come già detto, in cui il tipo Currency è un 
intero a 64 bit con massimo 4 cifre decimali.
Molte banche, ad esempio, rifiutano che tu scriva codice usando i 
floating point, ma richiedono che i calcoli avvengano tra interi.
Ovviamente, le cifre con cui hanno a che fare sono talmente alte 
che spesso neanche gli int a 64 bit vanno bene, per cui c'è 
bisogno di librerie ad aritmetica multipla.
Tutto questo lo dico, ovviamente, in base alla mia esperienza.


Si, ma io non lo uso per *rappresentare* il denaro, ma per fare una
operazione specifica (la divisione).
La valuta e' ''rappresentata'' con un intero.
Saluti  Manlio Perillo

 operazione specifica (la divisione).
Non va bene, secondo me.

approssimazione.  
Non va bene.
I soldi sono quantita' reali, non entita' matematiche.
Praticamente, come fai a darmi 1/3 di euro?
Per quanto riguarda la propagazione degli errori dovuti
all'arrotondamento, probabilmente la procedura e' soggetta a delle
convenzioni.
Magari la Matematica Finanziaria affronta e risolve questo problema
http://it.wikipedia.org/wiki/Matematica_finanziaria
Saluti  Manlio Perillo

 Praticamente, come fai a darmi 1/3 di euro?
Ti darò, presumibilmente, 33 centesimi, ma non è questo il punto.
Il valore utilizzato nei calcoli è 1/3 di euro.  La 
rappresentazione reale sarà poi 33 centesimi, approssimata.  Se 
eseguo, però, dei calcoli in cui sia coinvolto il valore di 1/3 di 
euro, lo farò utilizzando il valore esatto, non l'approssimazione.
Ad esempio, se ho un affitto di 1000 euro e devo dividerlo tra tre 
persone e ho una spesa del padrone di casa di 233 euro da dividere 
tra due delle persone che coabitano, allora avrò i valori divisi a 
questo modo:
persona A -> 1000/3
persona B -> 1000/3 + 233/2 = 2699/6
persona C -> 1000/3 + 233/2 = 2699/6
I valori sono esatti, poi ciò che andrà nelle tasche del padrone 
di casa sarà necessariamente approssimato ai centesimi.  I 
calcoli, però, li ho fatti tra valori precisi in modo assoluto.
Considera che i valori che ho preso sono solo esempi, è il succo 
del discorso che vale ;-)


Ma magari le convenzioni dicono di arrotondare per ogni operazione
''atomica''. Non credo che la cosa, vista la sua importanza, sia
lasciata alla discrezione dei singoli operatori. 
Ci sara', spero, una procedura da seguire.
Magari Nicola ne sa qualcosa.
Saluti   Manlio Perillo

 Magari Nicola ne sa qualcosa.
Infatti aspettiamo che si rifaccia sentire.  Magari leggendo la 
discussione, se la sta ridendo sotto i baffi ;-)

centesimo durante i calcoli, tutto qui.  
Va bene.
Ma come fai se magari ti accorgi che, oltre alle operazioni
elementari, devi anche(?) calcolare radici e/o esponenti?
Saluti  Manlio Perillo

 elementari, devi anche(?) calcolare radici e/o esponenti?
No no, io sto dando per scontate le operazioni elementari (che 
sono quelle che coinvolgono, normalmente, il denaro), *non* 
elevamenti a potenza.  Ammetto, comunque, che la matematica 
finanziaria potrebbe essere più complicata di quello che penso io.
Non conosco bene quel campo ;-)
Una radice è riconducibile a un'elevamento a potenza (radice 
quinta = elevamento a 1/5) ma rappresentare in modo esatto anche 
queste informazioni significherebbe, in fin dei conti, memorizzare 
delle formule e compiere calcoli tra formule.  Assurdo! :-)

 esperte non siano intimidite dalla tua competenza.
D'accordo. Ma credo che sai cosa penso.
Dirò solo che credo che la domanda non e la giusta. C'è un
aspetto legale molto importante ; ci sono operazioni con denari
dove la legge dice dal modo molto preciso cosa deve fare. E che
piutosto di una differenza fra dinari potentiale e dinari
effetivi, la differenza importante è fra i programmi che
producono documenti con valore legale, e quelli che producono
documenti solo "informativi".
--
James Kanze                                           GABI Software
Conseils en informatique orientée objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, 
+33 (0)1 30 23 00 34

 unsigned [long] long ints.
E come fai per calculare le scadenze ("échéances" in francese,
non sono certo dalla parole italiana) di un'ipoteca ? La formula
è :
    m = (K * (t/12)) / (1 - pow(1 + t/12, -n) ;
dove:
    K = il capitale
    t = il tasso d'interesso (anuale)
    n = il numero di mensualità


 non sono certo dalla parole italiana) di un'ipoteca ?
James, non ci tenere sulle spine!!! dicci come si fa :-))

 Come mai Boost non supporta un tipo Decimal o Currency?
Vedi 
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1150.pdf
.
Non è Boost, non è neanche C++ (ancora). Ma arriva certamente a
C++ più o meno tarde.


 operazioni realmente compiute; si sommano le entrate, si sottraggono le
A parte la rappresentazione "numerica" e quindi la scelta del 
"contenitore" adatto alla moneta qui ci si trova davanti a un problema 
di economia(filosofico). Sto aiutando la mia ragazza che studia economia 
a fare alcuni esami e da quanto ho capito un approccio valido e' il 
seeguente.
Una quantita' di denaro non rappresenta un valore in se, e in effetti 
ogni operazione finanziaria e' caratterizzata da IMPORTO e MOMENTO 
TEMPORALE in cui viene effettuato. Quindi il modo corretto di operare 
con i movimenti finanziari sarebbe di ATTUALIZZARE tutti i movimenti 
avvenuti a tempi diversi t0, t1 , t2 , t3  ad un tempo di riferimento tRIF.
In questo modo somme e sottrazioni di MOVIMENTI DI DENARO in tempi 
diversi si effettuano in grande velocità e assumono un senso 
particolare.(semplicemente si sommano e sottraggono i valori attualizzati)
UNa operazione di base da effettuare sul tipo numerico e' quindi la sua 
ATTUALIZZAZIONE che puo' essere una cosa rognosa soprattuto se i tassi 
di interesse variano nel tempo.
FAtemi sapere se implementeate qualcosa.
SAluti
Es semplice con i tasso di interese costante:
Verso cifra D in istante t1, quanto e' valore attualizzato Da istante trif??
Da=D*(1+i)^(trif-t1)
i interesse.
In regie di interesse composto , Correggetemi se sbaglio!!

documenti solo "informativi".
Infatti sospettavo una cosa del genere, e sarebbe assurdo se non fosse
cosi'.
Saluti  Manlio Perillo




Non cogli intieri, in ogni casa. La formula, l'ho dato nella mia
posta.
In fatti, revengo alla posta iniziale. Nicola ha parlato di
"denaro effettivo", dicendo che le operazioni usate più
comunemente sono addizione e sottrazione. Solo qui, c'è bene un
caso di "denaro effettivo", dove i valori devono essere
"essati", che usa non solo multiplicazione e divisione, ma anche
la potezza -- da un valore negativo. E per sfortuna, e un caso
dove la legge esigia una precisione assoluta. O piutosto, imposa
le regole di arrondato, che non coincidono con quelle di double.
E un po assurdo, ma anche se sai fare più preciso, non ne hai
dritto (in Francia e in Germania, in ogni caso, ma credo che e
universale).


Ciao,
Per non stare a rispondere cose simili a tanti messaggi rispondo al mio
messaggio originale, cercando di raccogliere e sintetizzare i
contributi arrivati finora.
1. Quantita' ed operazioni esatte
Qualcuno suggerisce di usare i double, ma non e' una soluzione
accettabile. I numeri in virgola mobile non consentono di rappresentare
esattamente la maggior parte dei numeri frazionari; in particolare sono
rappresentati esattamente solo numeri che si possono esprimere come
somme di potenze negative di due. Questo errore puo' essere amplificato
dalle operazioni compiute sui numeri fino a risultare evidente.
In questo caso l'arrotondamento non e' accettabile se hai versato 1000
euro e poi ne hai prelevati 50 vuoi vedere un saldo di 950, non di
949,99 ne di 950,01 .
Una soluzione piu' che adeguata per questa parte del problema e'
l'utilizzo di una rappresentazione in virgola fissa, che si ottiene
semplicemente moltiplicando i numeri per un'opportuna potenza del dieci
ed eseguendo addizioni e sottrazioni con numeri interi, che sono sempre
rappresentabili correttamente.
O almeno era una soluzione piu' che adeguata fino a quando qualcuno non
ha pensato di inventarsi l'Euro (non fraintendetemi, l'Euro e'
un'ottima cosa, solo complica un po' la vita). Lo stesso cliente di
prima se prima di versare 1000 euro aveva versato 1000000 di lire
potra' anche accettare di vedere un totale di 1516,46 euro o 2936270
lire, ma quando guarda il dettaglio dei movimenti si aspetta che i
mille euro siano sempre mille euro e che  il milione di lire resti un
milione di lire.
2. Quantita' ed operazioni approssimate
Un'idea interessante e' quella di rinviare il piu' possibile le
operazioni che introducono errori, utilizzando ad esempio la
rappresentazione esplicita di numeratore e denominatore per numeri
razionali, in modo da eseguire l'ultima divisione solo quando e'
effettivamente necessario. Questa e' una soluzione che puo' funzionare
se le operazioni coinvolte sono solo moltiplicazioni e divisioni.
In molti casi pero' le operazioni da compiere sono piu' complesse e
questa strada non puo' essere di aiuto [1]. Tra parentesi quando si
tratta di denaro che passa da una mano ad un'altra il criterio della
massima precisione possibile e' troppo arbitrario: generalmente ci deve
essere un'autorita', ad esempio la legge, che stabilisce come si deve
fare anche se esistono o se si sviluppano nel tempo tecniche piu'
precise [2].
Questo potrebbe comportare tra l'altro l'impossibilita' di utilizzare
una rappresentazione generica che fornisce operazioni elementari
componibili e la necessita' di implementare specifiche operazioni
complesse ad hoc.
Personalmente considererei denaro potenziale anche il calcolo delle
rate che il cliente deve pagare, ma e' certamente vero che il risultato
deve essere una cifra "tonda", certa e incontrovertibile.
Probabilmente la soluzione definitiva sara' davvero l'adozione di
librerie che usano una rappresentazione decimale esplicita, a patto che
incorporino o che consentano di configurare gli aspetti di precisione e
arrotondamento normalmente previsti da leggi e regolamenti.
3. Altri aspetti
Un altro aspetto interessante, ma che lascerei da parte, e' la gestione
dei cambi.
Trascurerei anche il problema sollevato da Fabiano: se ragioni
sull'evoluzione futura di somme di denaro fai delle ipotesi su come
evolvera' (ad es. quanto rendera', quanto giochera' l'inflazione, ecc.)
e devi decidere nei calcoli se riferirti al valore attuale o
all'ipotetico valore di un istante futuro.
alla prossima puntata scendiamo nel concreto, ovvero parliamo di
possibili implementazioni.
Ciao,
Nicola
[1] In realta' si potrebbe pensare di costruire una rappresentazione
simbolica anche per espressioni complesse, in modo da poter manipolare
la formula completa ed eventualmente semplificarla al momento del
calcolo.
[2] Questo vale anche per l'esempio discusso da Andrea e Manlio: se una
moneta da 1 centesimo non e' ripartibile, bisogna decidere
arbitrariamente come gestirla.

 
Forse non mi sono spiegato bene, il princio di attualizzare funziona 
anche verso il passato, ovvero .... il tref puo' essere tipo la data di 
creazione del conto e tutte le cifre attualizzate a tal momento, in 
questo caso l'evoluzioni degli interessi nel passato fino al presente, 
eccome se sono noti.
In caso ci tornero' altra volta
SAuti

arbitrariamente come gestirla.
Io sono indeciso tra:
1) giocarselo alla morra cinese
2) Dividere la monetina in parti uguali (con una sega)
3) Darla in beneficenza (ad una associazione da determinarsi)
4) Darla a Fazio
:-)
A parte gli scherzi, mi interessa molto l'osservazione che ha fatto
James sul denaro effettivo e potenziale e sul valore legale dei
software che fanno conti sui soldi.
Sto partecipando allo sviluppo di un gestionale (ma non sono un
esperto nel campo), la cosa e' in tema?
Saluti  Manlio Perillo

 leggi e regolamenti.
Qualcosa come
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1146.pdf
? E C,
ma penso che arriverà a C++ anche.


 ha scritto nel messaggio 
news:xfXgf.12229$tc5....@tornado.fastwebnet.it...


 ma penso che arriverà a C++ anche.
Questo si riferisce a varianti bounds checking di funzioni della
libreria standard C. Forse intendevi riferirti a
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1150.pdf
 ?
Ciao,
Nicola

piu'
Se uno somma per tre volte 1000/3, avrai sul tuo conto 1000 euro, come
č giusto che sia.  Quali centesimi in piů? (sono le 2.47, č probabile
che mi sfugga qualcosa ;-)

possibili implementazioni.
L'intera discussione è interessante e mi ha confermato, per lo meno,
che non ero del tutto sulla cattiva strada ;-)
Ho letto le prime otto pagine del documento riportato da James, in cui
si fa riferimento ai tipi Decimal a 32/64/128 bit e relative proposte
di modifica allo standard del linguaggio C.
La domanda però che mi pongo è se anche i sistemi di base dati sono
aggiornati a questo tipo di elaborazioni.  Cioé, che senso avrebbe
introdurre un sistema così altamente preciso, se i dbms, che sono i
sistemi su cui transitano le informazioni, nella maggior parte dei
casi, non offrono "tipi" per i propri campi che siano al passo con
questa precisione?



Infatti.







Se non va altramente, c'è sempre varchar. Ma infatti, limita le
possibilità di ricerca.
Ma credo che non è veramente il probleme. Il probleme è nel
calculo, non nella reprisentazione dei numeri. Se scrivi un
numero decimale preciso di 2 decimali in un double, il numero
nel double non è esattamente quello dal numero decimale. Ma se
lo rileggi verso il numero decimale, con due decimale di
precisione, devi ritrouvare di nuovo il valore decimale esatto.
Da essempio, se hai un valore decimale esatto di 2.23,
scrivendolo in un double da diciamo 2.
2299999998
. Ma
rileggendolo in un decimale con 2 ciffri di precisioni, da di
nuovo 2.23.


Ciao,
come probabilmente avete immaginato il mio quesito si basa su
un'esperienza concreta. In realta' nel caso in questione i requisiti si
sono presentati a distanza di tempo: in origine la necessita'
fondamentale per me riguardava la rappresentazione di quantita' di
denaro esatte.
In origine scegliemmo di usare la classe Currency delle librerie
Borland. Questa usa una rappresentazione in virgola fissa dove il
valore e' spiazzato di 4 cifre decimali (moltiplicato per 10.000) e
rappresentato su un intero a 64 bit. Finche' avevamo da sommare e
sottrarre versamenti e prelievi non incontrammo alcun problema.
Il primo problema lo incontrammo a causa di un aspetto discutibile
dell'implementazione Borland, ovvero la scelta, nelle moltiplicazioni,
di dividere arbitrariamente uno dei fattori per 10.000 prima di
eseguire la moltiplicazione. Notate che la divisione e' indispensabile,
perche' se abbiamo
a * b = c
e
A = a * 10000
B = b * 10000
C = c * 10000
allora avremo
A * B = a * b * 10000 * 10000 = C * 10000
Il problema e' quando effettuare la divisione. La soluzione piu' ovvia
e' prima moltiplicare i due numeri e poi dividere per 10000, ma non e'
detto che sia una buona idea. Il risultato intermedio risulta infatti
moltiplicato per 10 ^ 8. Questo corrisponde a circa 2 ^ 24 e comporta
che degli originali 64 bit ne restino circa 40 per rappresentare il
valore vero e proprio, cioe' grosso modo 10^13 . Non e' poco, ma non ci
si puo' rappresentare il debito pubblico in lire. Allora aggirammo il
problema scrivendo due funzioni per moltiplicazione e divisione, che
prima eseguivano l'operazione e poi aggiustavano la scala.
In seguito, un po' per questo motivo, ma soprattutto per svincolare dal
fornitore gli strati bassi dell'applicazione decidemmo di sostituire
Currency con una nostra classe. Nel frattempo Borland modifico' la
propria implementazione passando a comportarsi piu' o meno come le
nostre funzioni.
I dettagli alla prossima puntata.
Ciao,
Nicola