voidSet_DDS_Freq(unsignedlonglongFrequenz)// in Millihertz!!!
5
{
6
constunsignedlonglongintRef=300000000000;// in Millihertz!!!
7
unsignedshortintDummy;
8
unsignedcharACC,Byte[11],Teiler[5];
9
struct
10
{
11
unsignedcharCY:1;
12
unsignedcharF0:1;
13
}PSW;
14
15
Byte[10]=Frequenz>>32;
16
Byte[9]=Frequenz>>24;
17
Byte[8]=Frequenz>>16;
18
Byte[7]=Frequenz>>8;
19
Byte[6]=Frequenz>>0;
20
Byte[5]=0x00;
21
Byte[4]=0x00;
22
Byte[3]=0x00;
23
Byte[2]=0x00;
24
Byte[1]=0x00;
25
Byte[0]=0x00;
26
Teiler[4]=Ref>>32;
27
Teiler[3]=Ref>>24;
28
Teiler[2]=Ref>>16;
29
Teiler[1]=Ref>>8;
30
Teiler[0]=Ref>>0;
31
32
for(unsignedcharn=48;n;n--)
33
{
34
PSW.CY=0;
35
for(unsignedchari=0;i<=10;i++)
36
{
37
ACC=Byte[i];
38
Dummy=ACC+ACC+PSW.CY;//8051 RLC_A nachbilden
39
ACC=Dummy;
40
PSW.CY=Dummy>>8;
41
Byte[i]=ACC;
42
}
43
PSW.F0=PSW.CY;
44
if(PSW.CY==0)
45
{
46
for(unsignedchari=0;i<=4;i++)
47
{
48
ACC=Byte[i+6];
49
Dummy=ACC-Teiler[i]-PSW.CY;//8051 SUBB nachbilden
50
ACC=Dummy;
51
PSW.CY=Dummy>>8;
52
}
53
}
54
if(PSW.F0==1||PSW.CY==0)
55
{
56
PSW.CY=0;
57
for(unsignedchari=0;i<=4;i++)
58
{
59
ACC=Byte[i+6];
60
Dummy=ACC-Teiler[i]-PSW.CY;//8051 SUBB nachbilden
61
ACC=Dummy;
62
PSW.CY=Dummy>>8;
63
Byte[i+6]=ACC;
64
}
65
Byte[0]|=0x01;
66
}
67
}
68
//************** 48-Bit Ergebnis an DDS senden ************************
69
Set_DDS_Reg(0x04,Byte[5]);// Frequency Tuning Word 1 <47:40>
70
Set_DDS_Reg(0x05,Byte[4]);// Frequency Tuning Word 1 <39:32>
71
Set_DDS_Reg(0x06,Byte[3]);// Frequency Tuning Word 1 <31:24>
72
Set_DDS_Reg(0x07,Byte[2]);// Frequency Tuning Word 1 <23:16>
73
Set_DDS_Reg(0x08,Byte[1]);// Frequency Tuning Word 1 <15:8>
74
Set_DDS_Reg(0x09,Byte[0]);// Frequency Tuning Word 1 <7:0>
75
}
Ein 88-Bit Word wird durch ein 40-Bit Word geteilt, das Ergebnis hat
48-Bit. Es funktioniert sogar!
Nun meine Frage:
1. Kann man das auch anders lösen? Eventuel wirklich Assembler
einbinden, anstatt einen alten 8051-Code in C nachzubilden?
2. Ist diese Division überhaupt nötig?
Die Rechnung benutzt am Anfang eine 88-Bit-Zahl, also wesentlich mehr
als 64 Bit (long long). Eine Möglichkeit - Voraussetzung: ausreichend
lange Mantisse entsprechender Floating-Point-Zahlen - besteht darin, mit
Floating-Point-Zahlen (Frequenz ebenfalls in MilliHertz!!!) zu rechnen
und die Zahlen zur Ausgabe nach long long umzuformen. Das war zu Zeiten
der 16-Bit PCs im Bankenbereich recht elegant: Beträge wurden definiert
als Pfennige und in double gerechnet.
Bernhard
Bernhard R. schrieb:> der 16-Bit PCs im Bankenbereich recht elegant: Beträge wurden definiert> als Pfennige und in double gerechnet.
Ganz sicher nicht.
double hat im Bankbereich überhaupt nichts zu suchen. Jedes Finanzamt
oder Bankenaufischt schmeisst dir so einen Code (mit Recht) sofort um
die Ohren.
Karl Heinz Buchegger schrieb:> Bernhard R. schrieb:>>> der 16-Bit PCs im Bankenbereich recht elegant: Beträge wurden definiert>> als Pfennige und in double gerechnet.>> Ganz sicher nicht.> double hat im Bankbereich überhaupt nichts zu suchen. Jedes Finanzamt> oder Bankenaufischt schmeisst dir so einen Code (mit Recht) sofort um> die Ohren.
Ist da eigentlich decimal float erlaubt?
Karl Heinz Buchegger schrieb:> Ganz sicher nicht.> double hat im Bankbereich überhaupt nichts zu suchen. Jedes Finanzamt> oder Bankenaufischt schmeisst dir so einen Code (mit Recht) sofort um> die Ohren.
Es wurde tatsächlich so gemacht und lief fehlerfrei. Wenn Du z.B. 50
Millionen DM mit 0,01 DM addierst, geschieht:
5.000.000.000,0 Pfennige
+ 1,0 Pfennig
sind
5.000.000.001,0 Pfennig. Versuche das bitte mit 32-Bit-Integer zu
rechnen.
Zur Umwandlung in menschenlesbare Werte waren nicht einmal spezielle
Routinen erforderlich.
Dieses Verfahren war in mehr als nur einer Bank üblich.
Allerdings widersprechen sich auf den ersten flüchtigen Blick das
Zahlenformat "double" und kaufmännische Anforderungen.
Bernhard
Bernhard R. schrieb:> Karl Heinz Buchegger schrieb:>> Ganz sicher nicht.>> double hat im Bankbereich überhaupt nichts zu suchen. Jedes Finanzamt>> oder Bankenaufischt schmeisst dir so einen Code (mit Recht) sofort um>> die Ohren.>> Es wurde tatsächlich so gemacht und lief fehlerfrei. Wenn Du z.B. 50> Millionen DM mit 0,01 DM addierst, geschieht:> 5.000.000.000,0 Pfennige> + 1,0 Pfennig> sind>> 5.000.000.001,0 Pfennig. Versuche das bitte mit 32-Bit-Integer zu> rechnen.
Dann nimmt man längere Integer bzw ein Format das mit BCD arbeitet.
Aber spätestens nach dem Versuch 10 Stück 0.1 zu addieren und da kommt
dann nicht 1.0 heraus, ist double auf ganzer Linie gescheitert.
Buchhaltungsprogrammierer (genauso wie Bänker) haben Monate gesucht um
fehlende Pfennige in ihren Programmen zu finden, die sie irgendwo bei
Zinseszinsrechnungen verloren haben.
double mag für den Berater ok sein, der dir auf seinem Excel mal schnell
die Ratenbelastung für einen Kredit ausrechnet. Aber auf dem
Grossrechner, der die Konten führt, gibts kein double.
Hallo Karl Heinz,
ich arbeite (mit Unterbrechung) schon 20J in Unternehmen, die Software
für Banken schreiben.
Das (double als Zahlenformat) wurde (und wird immer noch zum Teil)
gemacht. Mir haben sich da auch schon öfter die Fussnägel aufgerollt.
Dabei gibts doch - wie du schon gesagt hast- BCD Zahlen.
U.R. Schmitt schrieb:> Hallo Karl Heinz,> ich arbeite (mit Unterbrechung) schon 20J in Unternehmen, die Software> für Banken schreiben.> Das (double als Zahlenformat) wurde (und wird immer noch zum Teil)> gemacht. Mir haben sich da auch schon öfter die Fussnägel aufgerollt.> Dabei gibts doch - wie du schon gesagt hast- BCD Zahlen.
Und das geile daran: die gibt es von Anfang an. Waren in COBOL schon
gang und gäbe und wurden extra für diesen Zweck eingebaut.
Karl Heinz Buchegger schrieb:> Dann nimmt man längere Integer bzw ein Format das mit BCD arbeitet.
Warum sollte man auch mit double arbeiten, da spendiert man 64 bit und
hat nur 52 Bit Mantisse.
Da verwendet man doch besser gleich long long und hat die vollen 64 bit.
Meines Wissen hat Cobol die BCD Arithmetik nativ untersützt.
Karl Heinz Buchegger schrieb:> Aber spätestens nach dem Versuch 10 Stück 0.1 zu addieren und da kommt> dann nicht 1.0 heraus, ist double auf ganzer Linie gescheitert.
Warum sollte man das denn machen? Es geht um Pfennige/Cent. Und bei
Integern geht das auch nicht (0,1 Cent addieren).
DirkB schrieb:> Karl Heinz Buchegger schrieb:>> Aber spätestens nach dem Versuch 10 Stück 0.1 zu addieren und da kommt>> dann nicht 1.0 heraus, ist double auf ganzer Linie gescheitert.>> Warum sollte man das denn machen?
Weil es in Banken nun mal nicht so selten vorkommt, dass viele Zahlen
addiert werden müssen? Und diese Zahlen durch Zinsberechnung schon auch
mal krumme Werte ergeben?
> Es geht um Pfennige/Cent. Und bei> Integern geht das auch nicht (0,1 Cent addieren).
Warum nimmt man dann nicht gleich entsprechend große Integer?
Und wie machen Banken eine Division? Die geht doch meist nicht als
Integer auf.
Transzendente oder zumindest irrationale Zahlen?? Zinzeszins? Verwenden
die wenigstens Brüche als interne Darstellung? Gibts einen Standard, der
die Anforderungen und letztendlichen Ungenauigkeiten definiert?
Und eine Geldsumme, die insgesamt begrenzt ist, würde mich auch wundern.
Abdul K. schrieb:> Transzendente oder zumindest irrationale Zahlen??
Warum sollte ein double Format solche solche Zahlen besser darstellen?
Und Divisionen lassen sich mit BCD genauso rechnen wie mit double.
Dass die Division von float und doubles von der Hardware unterstützt
ist, und deshalb schneller ist, hat aber mit dem Prinzip nichts zu tun.
brushless schrieb:> @ kleiner Programmierer,>> schau Dir mal das an:> Beitrag "große Zahl (lomg long) und trotzdem genau ?">> Gruß Mattias
Hallo Mattias,
du hast damals zuletzt dieses gehabt:
1
#define X (2814749767107)
2
unsigned(longlong)t_word;
3
unsignedinti,j,k,l,m;
4
5
6
t_word=
7
(i*X)+
8
(j*(X/1000))+
9
(unsignedlong)(
10
(k*(X/1000000))+
11
(l*(X/1000000000))+
12
(m*(X/1000000000000)));
Die Nano-Hertz lässt du (zu recht?) unter den Tisch fallen.
Bei der Berechnung der µHz ergibt
2814749767107/1000000000000 = 2
Hier verschenkst du Auflösung, der DDS hat immerhin eine Auflösung von
100MHz (Ref) / 2^48 = 355 nHz
Da ich nicht nur einen DDS-Baustein programmieren will, sondern meinen
Programmierstil noch verbessern wollte, zielt dieser Thread eher darauf,
ob das Programmiertechnisch alles OK ist, ob man da noch was ändern
sollte.
Wenn long long nicht mehr reicht, kann man auch zu Libraries für Rechnen
mit beliebig langen Zahlen greifen. Stichworte: Arbitrary Precision
Arithmetic oder Bignum.
>Buchhaltungsprogrammierer (genauso wie Bänker) haben Monate gesucht um>fehlende Pfennige in ihren Programmen zu finden, die sie irgendwo bei>Zinseszinsrechnungen verloren haben.
GAbs da nicht mal einen Fall, wo ein Banker diese fehlenden Bruchteile
von Pfennigen auf sein Konto umgeleitet hat?
brushless schrieb:> Bei Banken wird gar nicht gerechnet, die schätzen immer nur...
Und der fehlende Betrag ersetzt die Regierung :-)
Deshalb sind die auch alle in den roten Zahlen.
Zunächst einmal:
Ich habe mich offensichtlich mißverständlich ausgedrückt. In
Bankanwendungen - wo es um Geld zählen geht, werden Berechnungen mit
recht großen Integer-Werten benötigt. Vor knapp 30 Jahren, zu Zeiten von
16-Bit CPUs im PC, besaß die größte darstellbare Integer-Zahl vieler
C-Compiler 32 Bit; das entsprach ca. 40 Millionen DM - nicht genug.
Eine einfache Methode, Integer-Werte mit mehr als 32 Bit darzustellen,
bestand darin, mit double-Werten zu arbeiten - sorgfältigst skaliert, um
ja nicht in Rundungsprobleme hineinzulaufen. Das war immer noch
wesentlich weniger aufwendig, als eine entsprechende Library mit
längeren Integern zu implementieren!
U.R. Schmitt schrieb:> ich arbeite (mit Unterbrechung) schon 20J in Unternehmen, die Software> für Banken schreiben.> Das (double als Zahlenformat) wurde (und wird immer noch zum Teil)> gemacht. Mir haben sich da auch schon öfter die Fussnägel aufgerollt.> Dabei gibts doch - wie du schon gesagt hast- BCD Zahlen.
Auf dem Host - z.B. IBM 309x, heute Z-Series - wurden diese Beträge aus
bereits damals historischen Gründen zum Teil sogar als "POV" (gepackt
ohne Vorzeichen) gespeichert und ausschließlich für Berechnungen in ein
von der CPU bearbeitbares Format überführt.
Zurück zum Problem des TO:
Ich würde diese eine Berechnung mit Floating-Point-Arithmetik lösen,
sofern der Datentyp "double" eine ausreichende Anzahl signifikanter Bits
zur Verfügung stellt. Ein kleiner Kommentar mit Erläuterung der
Genauigkeitsanforderungen dürfte zu verständlichem Code führen.
Bernhard
Bernhard R. schrieb:> Karl Heinz Buchegger schrieb:>> Ganz sicher nicht.>> double hat im Bankbereich überhaupt nichts zu suchen. Jedes Finanzamt>> oder Bankenaufischt schmeisst dir so einen Code (mit Recht) sofort um>> die Ohren.>> Es wurde tatsächlich so gemacht und lief fehlerfrei. Wenn Du z.B. 50> Millionen DM mit 0,01 DM addierst, geschieht:> 5.000.000.000,0 Pfennige> + 1,0 Pfennig> sind>> 5.000.000.001,0 Pfennig. Versuche das bitte mit 32-Bit-Integer zu> rechnen.>> Zur Umwandlung in menschenlesbare Werte waren nicht einmal spezielle> Routinen erforderlich.>> Dieses Verfahren war in mehr als nur einer Bank üblich.>> Allerdings widersprechen sich auf den ersten flüchtigen Blick das> Zahlenformat "double" und kaufmännische Anforderungen.
Nicht nur auf den ersten Blick, jedenfalls für Leute die wissen was sie
tun. Man kann entweder garantieren dass die Rechnung stimmt oder es
ist per Definition Pfusch. Wer sagt denn dass ein paar Mios ausreichen,
die Bilanzsumme einer Bank kann ja theoretisch beliebig gross sein?
Mit Double ist schon das GDP der USA oder der EU zu gross wenn man in
Cent rechnet (man braucht normalerweise auch Centbruchteile) - Epic
Fail.
Das Stichwort hier wäre BigInt-Library (i.e. Integer unbegrenzter
Länge), gibt es schon seit den Zeiten der Dinosaurier oder so.
Matthias Lipinsky schrieb:>>Buchhaltungsprogrammierer (genauso wie Bänker) haben Monate gesucht um>>fehlende Pfennige in ihren Programmen zu finden, die sie irgendwo bei>>Zinseszinsrechnungen verloren haben.>> GAbs da nicht mal einen Fall, wo ein Banker diese fehlenden Bruchteile> von Pfennigen auf sein Konto umgeleitet hat?
Es gab mal einen Film, in dem das die Handlung war.
Karl Heinz Buchegger schrieb:> double hat im Bankbereich überhaupt nichts zu suchen. Jedes Finanzamt> oder Bankenaufischt schmeisst dir so einen Code (mit Recht) sofort um> die Ohren.
Du glaubst auch noch an Recht und Ordnung ;-)
Been there, seen that - eigentlich sollte ich nach der Erfahrung mein
Geld in der Matratze verstecken.
Da gabs doch mal den Fall, das eine Rechnung versendet wurde weil "-0"
als Ergebnis draufstand. Offensichtlich ein hochgenauer Mathematiker
als Programmierer in dem Unternehmen ;-)