<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
<title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Danke für die ausführliche Info.<br>
Da bleibt mir halt nichts anderes übrig, als die Windows-Typen
nachzuimplementieren.<br>
Eingentlich geht's mir auch gar nicht so um die Brechnungen als um die
verlustfreie Übertragung von Daten.<br>
Ich implementiere zur Zeit einen platformunabhängigen VARIANT, der
unter anderem auch die Typen CY und DECIMAL aufnehmen muss.<br>
Dabei Müssen Arrays von Werten (Prozessdaten) verschiedener Typen, die
als VARIANT bei DCOM oder als anyType bei SOAP übertragen werden<br>
auch auf Linux entsprechend in einen eigenen VARIANT aus unserer C++
API gewandelt werden.<br>
Interpretieren muss ich die Strukturieren nur soweit, dass ich die
Typen bei einem VariantChangeType-Aufruf in anderen Typen umwandeln
kann.<br>
Zum Beispiel bei der Darstellung als String.<br>
Andere arithmetische Funktionen brauche ich zum Glück nicht.<br>
<br>
Z.Info die Windows-Definitionen aus wtypes.h.<br>
DECIMAL: hier beträgt der Wert Lo64 * 10 ^ -scale<br>
Über das sign in signscale bin ich mir noch nicht klar, da der Wert nur
in eine Richtung skaliert werden kann soweit ich gesehen habe.<br>
typedef struct tagDEC {<br>
USHORT wReserved;<br>
union {<br>
struct {<br>
BYTE scale;<br>
BYTE sign;<br>
};<br>
USHORT signscale;<br>
};<br>
ULONG Hi32;<br>
union {<br>
struct {<br>
#ifdef _MAC<br>
ULONG Mid32;<br>
ULONG Lo32;<br>
#else<br>
ULONG Lo32;<br>
ULONG Mid32;<br>
#endif<br>
};<br>
ULONGLONG Lo64;<br>
};<br>
} DECIMAL;<br>
<br>
CY: hier ist die Precision konstant<br>
z.B.: Wert = int64 * 10 ^ -4<br>
typedef union tagCY {<br>
struct {<br>
#ifdef _MAC<br>
long Hi;<br>
long Lo;<br>
#else<br>
unsigned long Lo;<br>
long Hi;<br>
#endif<br>
};<br>
LONGLONG int64;<br>
} CY;<br>
<br>
Christian Stimming wrote:
<blockquote cite="mid200411131430.57403.stimming@tuhh.de" type="cite">
<pre wrap="">Am Freitag, 12. November 2004 11:03 schrieben Sie:
</pre>
<blockquote type="cite">
<pre wrap="">ich habe da mal eine Frage zu fixed precision data types unter Linux.
Unter Windows gibt es da den DECIMAL type, der eben speziell für
finanzielle Berechnungen eingesetzt wird, damit man im Gegensatz zu
Floating-Points immer die gleiche Precision hat.
Was gibt es da vergleichbares unter Linux?
Bei GnuCash wird so was ja auch bestimmt eingesetzt.
</pre>
</blockquote>
<pre wrap=""><!---->
Es gibt unter Linux/Posix-Unix keinen allgemein verwendeten Typen, der sowas
macht!!!
Man muß sich also in jeder Software selber aus den Basistypen eine passende
structure zusammenbauen und die dann verwenden. Die Frage ist also völlig
berechtigt und ich habe kurzerhand mal nachgesehen, was die ganzen
OpenSource-Programme so haben:
GnuCash
-----------
In Gnucash war seinerzeit (Mitte 2000) die Entscheidung getroffen worden, daß
man "rationale Zahlen" benutzt, also einen ganzzahligen Zähler und Nenner,
siehe src/engine/gnc-numeric.h:
struct _gnc_numeric {
gint64 num;
gint64 denom;
};
siehe auch <a class="moz-txt-link-freetext" href="https://cvs.gnucash.org/cgi-bin/cvsweb.cgi/gnucash/src/engine/">https://cvs.gnucash.org/cgi-bin/cvsweb.cgi/gnucash/src/engine/</a>
gnc-numeric.h?rev=1.23 -- unbedingt den CVS-HEAD branch verwenden und nicht
die Version im 1.8.x-Branch, da in HEAD sehr viel mehr Dokumentation drin
ist.
[Der Typ "gint64" kommt aus der glib (der glib von Gnome, nicht zu verwecheln
mit der glibc), weil innerhalb der glib für die unterschiedlichen Plattformen
die passenden typedefs gesetzt werden, so daß die Applikation sich bei gint64
darauf verlassen kann, daß das überall 64 bits sind. Aber das nur am Rande.]
In Gnucash sind wir also zu rationalen Zahlen gegangen (und der code darf
gemäß GPL gerne woanders weiterverwendet werden), aber wahrscheinlich war das
ein overkill. Fix-Point Zahlen, also etwas Ganzzahliges mit fester
Komma-Position, wären wahrscheinlich in der Implementierung wesentlich
einfacher gewesen. Nichtsdestotrotz müsste man auch dabei eben alle
arithmetischen Operationen für den neuen Typ einbauen und dabei für alle
Möglichkeiten bei Rundungen sich die Auswahlmöglichkeiten überlegen (also ob
die zusätzlichen Nachkommastellen beim Multiplizieren nachher gerundet werden
oder nicht etc). Und in der Implementierung wäre ich nicht auf Anhieb so
sicher, wie genau man das machen würde -- da man ja Binärzahlen hat, wäre es
mit der einfachen Angabe "Nachkommastellen zur Basis 10" ja nicht erledigt,
denn die gespeicherte Ganzzahl ist ja eine Ganzzahl zur Basis 2. Wie auch
immer. In Gnucash gibts halt die Brüche mit einer hoffentlich vollständig
richtigen Implementierung und die verwenden wir nun mal.
KMyMoney
-------------
Tja, offensichtlich haben die Kollegen dort das mit der GPL bereits ganz
richtig verstanden :-) . Im Februar 2004 haben die nämlich ihrerseits den
Umstieg von "double"-Werte zu ganzzahligen Werten gemacht, und sie haben dazu
genau den GnuCash-Code aus gnc-numeric.h/c rüberkopiert und in eine C+
+-Klasse umgeschrieben. Wenn du also so eine Implementation mit rationalen
Zahlen in C++ suchst, dann findest du die in kmymoney2, Klasse MyMoneyMoney
in mymoneymoney.h.
Grisbi
------
Die Herren von der Gtk2-Konkurrenz dagegen sind noch dabei stehengeblieben,
daß die Finanz-Werte als "double" gespeichert werden. Denen steht der Umstieg
also noch bevor -- aber vorher müssten die sich eh noch von der französischen
Sprache im Quelltext lösen...
QBankManager
Die einfache Applikation QBankManager, die ja nur zum schnellen Verwalten des
HBCI-Zugangs dienen soll, benutzt intern ebenfalls nur "double"-Werte (aus
AB_VALUE). Für den Import/Export von Daten sind "double"s wohl auch ok, denn
Rundungsfehler bekommt man ja erst bei arithmetischen Operationen mit vielen
dieser Werte (also z.B. beim laufenden Saldo eines Kontos).
Gruß
Christian Stimming
</pre>
</blockquote>
<br>
<br>
<div class="moz-signature">-- <br>
mit freundlichen Grüßen / best regards<br>
<br>
<b>Gerhard Gappmeier</b><br>
ascolab GmbH - automation system communication laboratory<br>
Tel.: +49 9131 691 123<br>
Fax: +49 9131 691 128<br>
Web: <a class="moz-txt-link-freetext" href="http://www.ascolab.com">http://www.ascolab.com</a><br>
GPG-Key: <a class="moz-txt-link-freetext" href="http://www.ascolab.com/pgp/gerhard.asc">http://www.ascolab.com/pgp/gerhard.asc</a><br>
</div>
</body>
</html>