Forum: Compiler & IDEs wenn long long nicht mehr reicht


von Kleiner Programmierer (Gast)


Lesenswert?

Hi,
um einen 48 Bit DDS Synthesizer anzusteuern brauche ich eine eine 
Division mit 48 Bit Ergebnis.
Ich habe das im Moment so gelöst:
1
//**********************************************************************
2
//***** Ergebnis(48-Bit) = Frequenz(40-Bit) * 2^48 / Ref(40-Bit) *******
3
//**********************************************************************
4
void Set_DDS_Freq(unsigned long long Frequenz) // in Millihertz!!!
5
{
6
const unsigned long long int Ref=300000000000; // in Millihertz!!!
7
unsigned short int Dummy;
8
unsigned char ACC,Byte[11],Teiler[5];
9
struct
10
{
11
  unsigned char CY:1;
12
  unsigned char F0: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(unsigned char n=48;n;n--)
33
{
34
  PSW.CY=0;
35
  for(unsigned char i=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(unsigned char i=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(unsigned char i=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?

von Bernhard R. (barnyhh)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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?

von Bernhard R. (barnyhh)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von U.R. Schmitt (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Klaus F. (kfalser)


Lesenswert?

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.

von DirkB (Gast)


Lesenswert?

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).

von Karl H. (kbuchegg)


Lesenswert?

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?

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

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.

von Klaus F. (kfalser)


Lesenswert?

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.

von brushless (Gast)


Lesenswert?

Bei Banken wird gar nicht gerechnet, die schätzen immer nur...

@ kleiner Programmierer,

schau Dir mal das an:
Beitrag "große Zahl (lomg long) und trotzdem genau ?"

Gruß Mattias

von Horst (Gast)


Lesenswert?

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 (long long) t_word;
3
unsigned int i,j,k,l,m;
4
5
6
t_word =
7
(i * X) +
8
(j * (X / 1000)) +
9
(unsigned long) (
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.

von Andreas B. (Gast)


Lesenswert?

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.

von Matthias L. (Gast)


Lesenswert?

>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?

von Helmut L. (helmi1)


Lesenswert?

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.

von Bernhard R. (barnyhh)


Lesenswert?

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

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Ich würde zuerst mal bei AD und silabs nach AppNotes diesbezüglich 
schauen.

von Jasch (Gast)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von Jürgen (Gast)


Lesenswert?

Wo wir gerade beim Thema Banken und Fließkommazahlen sind:

Hat schon mal jemand die dezimalen Fließkommazahlen aus IEEE754 in 
freier Wildbahn gesehen?

von Klaus W. (mfgkw)


Lesenswert?

nee, noch nicht einmal in IEEE 754.


Meinst du 854 oder den Entwurf 754r ?

von P. S. (Gast)


Lesenswert?

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.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

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 ;-)

von Jürgen S. (starblue) Benutzerseite


Lesenswert?

> Meinst du 854 oder den Entwurf 754r ?

Ich meine IEEE 754-2008.

http://en.wikipedia.org/wiki/IEEE_754-2008

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.