Forum: PC-Programmierung C++ , Berechnung Fakultät mit BCD-Charakter-Arrays


von LeDay (Gast)


Lesenswert?

Guten Abend,

ich möchte ein Programm für einen Atmega Mikrocontroller schreiben, mit 
dem man große Fakultäten berechnen kann.
Da ein jener Mikrocontroller nicht über eine riesige Menge an 
Speicherplatz verfügt, möchte ich nicht wie bei dem aktuellen Stand 
meines Programms pro Zahl ein Charakter-Array-Element verwenden,
sondern möchte in jedes Charakter-Array-Element zwei BCD-codierte Zahl 
abspeichern.
Ich verwende ein großes Array, um das Ergebnis jeder Multiplikation 
darin abzuspeichern und anschließend für die weitere Berechnung zu 
verwenden.
Das Element 0 des Arrays ist meine niederwertigste Zahl und die Zahl vor 
meinem terminierenden '0xFF' ist die höchstwertigste Zahl.

Mir fehlt nun leider der richtige Denkanstoß, wie ich korrekt die obere 
Hälfte und die untere Hälfte eines 8-Bit-Charakter anspreche.
Ich überlegte mir dies mit bitweiser Verundung/Veroderung und mit 
Bitschiebeoperationen.
Dies habe ich dann versucht und bin leider gescheitert.
Gibt es eine einfachere Möglichkeit das mit den BCD-Zahlen zu 
realisieren?
Ich brauche nur einen Denkanstoß bzw. ein kleines Beispiel.
Vielleicht könnt ihr mich auch auf uneffektive Stellen in meinem Code 
hinweisen.

Anbei mein Programm, dass ich für den Ablauf am PC etwas abgeändert 
habe(Ausgabe) (lauffähig für C++ Compiler)

Mit freundlichen Grüßen
LeDay
1
#include <iostream>
2
using namespace std;
3
#define SIZEUCHAR 500000 
4
#define BIN_STR_TERM 0xFF
5
6
long funct(unsigned char* erg, unsigned long* mult)
7
{
8
  unsigned long k = 0, l = 0;
9
  unsigned long temperg = 0, tempmult = 0;
10
  while (erg[k] != BIN_STR_TERM)
11
  {
12
    tempmult = *mult;
13
    l = 1;
14
    while (tempmult)
15
    {
16
      temperg = temperg + erg[k] * (tempmult % 10)*l;
17
      tempmult = tempmult / 10;
18
      l = l * 10;
19
    }
20
    erg[k] = temperg % 10;
21
    temperg = temperg / 10;
22
    k++;
23
  }
24
  while (temperg)
25
  {
26
    erg[k] = temperg % 10;
27
    temperg = temperg / 10;
28
    k++;
29
  }
30
  erg[k] = BIN_STR_TERM;
31
  return (k);
32
33
}
34
int main()
35
{
36
  unsigned long StelleEndeZahl = 0;
37
  unsigned long zaehl = 0;
38
  while (1)
39
  {
40
    long Eingabe = -1;
41
    while ((Eingabe < 0) || (Eingabe >= 100000))
42
    {
43
      cout << "Geben Sie eine positive Ganzzahl zur Berechnung ihrer Fakultaet an: ";
44
      cin >> Eingabe;
45
    }
46
    unsigned char Ergebnis[SIZEUCHAR] = { 1,BIN_STR_TERM };
47
    if (Eingabe == 0)
48
      cout << 1;
49
    else {
50
      for (zaehl = 1; zaehl <= Eingabe; zaehl++)
51
      {
52
        StelleEndeZahl = funct(Ergebnis, &zaehl);
53
      }
54
      while (StelleEndeZahl != 0)
55
      {
56
        StelleEndeZahl--;
57
        cout << (char)(Ergebnis[StelleEndeZahl] + 48); // +48 um als ASCII-Zeichen auszugeben
58
      }
59
    }
60
    cout << endl;
61
  }
62
}

von guest (Gast)


Lesenswert?

LeDay schrieb:
> Ich überlegte mir dies mit bitweiser Verundung/Veroderung und mit
> Bitschiebeoperationen.
> Dies habe ich dann versucht und bin leider gescheitert.

Wo ist das Problem?
1
uint8_t bla;
2
bla & 0x0f;  // lower nibble
3
bla >> 4;    // upper nibble

von S. R. (svenska)


Lesenswert?

LeDay schrieb:
> Da ein jener Mikrocontroller nicht über eine riesige Menge an
> Speicherplatz verfügt, möchte ich nicht wie bei dem aktuellen Stand
> meines Programms pro Zahl ein Charakter-Array-Element verwenden,
> sondern möchte in jedes Charakter-Array-Element zwei BCD-codierte Zahl
> abspeichern.

Wenn du einen Integer in einem Byte speicherst, dann kannst du in 8 Bits 
die Werte von 0 bis 255 speichern (also 8 Bit an Information).

Wenn du stattdessen eine gepackte BCD-Zahl in einem Byte speicherst, 
dann kannst du in 8 Bits die Werte von 0 bis 99 speichern (also 6.63 Bit 
an Information).

Also sind 8 Bit-Integer ungefähr 20% speichereffizienter als 8 Bit 
packed BCD. Dazu kommt noch, dass BCD-Arithmetik vom AVR nicht direkt 
unterstützt wird, du also zusätzlich Rechenzeit und Flashspeicher 
brauchst, um damit zu arbeiten.

von tictactoe (Gast)


Lesenswert?

Ich würde außerdem nicht BCD verwenden, weil das fürs Rechnen echt 
Scheibenkleister ist. Besser ist es, in einem Byte ganz normal mit den 
Werten 0 bis 99 zu rechnen. Verschenkt zwar ein Bit, aber ist noch 
relativ bequem zum Umwandeln in Dezimaldarstellung.

Alternativen wären noch uint16_t mit 0 bis 9999 (kein echter Gewinn). 
Oder, wenn man sowieso gaaaanz große Zahlen arbeiten will, uint32_t mit 
0 bis 1e9-1 da hat man gleich eine ganze Dezimalstelle mehr als mit zwei 
uint16_t.

von LeDay (Gast)


Lesenswert?

@tictactoe , Vielen Dank für die Idee einfach die Zahlen 0-99 in einem 
char-Element zu verwenden.
Ich habe das jetzt so umsetzen können. Es führte auch zu einer deutlich 
gesteigerten Geschwindigkeit.

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.