C++ , Berechnung Fakultät mit BCD-Charakter-Arrays

Gast #5654837
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
}
#5654951
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.
Gast #5655111
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.
Gast #5657131
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren