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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von LeDay (Gast)


Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
2 lesenswert
nicht 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)


Bewertung
2 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.