BCD-Format



  • Vielen Dank für die tolle Hilfe! Ich hoffe ihr wurdet reichlich beschenkt! :xmas1:

    Wenn ich das jetzt richtig sehe, kann ich den BCD-Code nicht wie eine normale Zahl (wie z.B. einen double oder int) verwenden oder? Jede Ziffer hat ja ihre eigene Belegung im Array.

    Wie integriert man diesen BCD-Code, wenn ich noch eine erweiterte Funktion erstellen möchte bzw. muss, der mit diesem Code arbeiten soll?



  • kapitel funktionen in deinem c buch



  • Ich habe hier jetzt eine Funktion, mit der ich den BCD-Code von führenden und angehängten Nullen reinige.

    struct bcd_number * clean_bcd(struct bcd_number *b){
    
        int i,j=0,k=0;
    
        for (i=0; i < b->laenge; i++) {
    
            while (b->ziffern[i] == 0) {
    
                j++;
            }
        }
    
        for (i=0; i < b->laenge; i++){
    
            b->ziffern[i] = b->ziffern[i+j];
        }
    
        for (i=0; i < b->laenge; i++){
    
            if( b->ziffern[i] == 0){
                k++;
            }
            else k=0;
    
        }
        b->laenge = b->laenge - (j+k);
        b->nachkommastellen = j - k; 
    
        return b;
    }
    
    int main( void ) 
    { 
        double eingabe = -2345.2; 
        struct bcd_number* bcd; 
        int i; 
    
        bcd = string2bcd (eingabe); 
    
        printf ("Eingabe:              %f\n",eingabe); 
        printf ("bcd.laenge:           %u\n",bcd->laenge); 
        printf ("bcd.nachkommastellen: %u\n",bcd->nachkommastellen); 
        printf ("bcd.vorzeichen:       %i\n",bcd->vorzeichen); 
        printf ("bcd.ziffern:          "); 
        for (i=0; i<bcd->laenge; ++i) printf ("%i ",bcd->ziffern[i]); 
        puts ("\n"); 
    
        clean_bcd(bcd);
        printf ("Eingabe:              %f\n",eingabe); 
        printf ("bcd.laenge:           %u\n",bcd->laenge); 
        printf ("bcd.nachkommastellen: %u\n",bcd->nachkommastellen); 
        printf ("bcd.vorzeichen:       %i\n",bcd->vorzeichen); 
        printf ("bcd.ziffern:          "); 
        for (i=0; i<bcd->laenge; ++i) printf ("%i ",bcd->ziffern[i]); 
        puts ("\n"); 
    
        free (bcd->ziffern); 
        free (bcd); 
    
        return 0; 
    }
    

    Leider steht da nach dem compilieren nichts für die werte nach clean_bcd(bcd) . Weiß jemand wo ich hier den Fehler habe?



  • Deine Funktion kann nicht funktionieren.
    Wenn da wirklich ein 0 am Anfang ist, bleibst du bei dem j++ in einer Endlosschleife hängen.

    Die Nullen am Ende solltest du aber nur entfernen, wenn sie wirklich bei den Nachkommastellen sind.

    Benutze den Debbuger oder baue dir Zwischenausgaben in deine Funktion ein.



  • Siegfried101 schrieb:

    Ich habe hier jetzt eine Funktion, mit der ich den BCD-Code von führenden und angehängten Nullen reinige.

    Wer zwingt Dich nur, vor Jahresende so etwas zu tun? 😃
    Ich hab Dir mal ein Prüfprogramm entworfen, damit Du auch ein paar Nullen zum Herumspielen hast:

    #include <stdio.h>
    
    struct bcd_number
    {
    	unsigned int laenge;
    	unsigned int nachkommastellen;
    	signed char vorzeichen;
    	unsigned char *ziffern;
    };
    
    struct bcd_number * clean_bcd(struct bcd_number *b)
    {
        unsigned int i, j=0, imax, imin;
    
    	/* Führende Vorkomma-Nullen eliminieren */
    	imax = b->laenge - b->nachkommastellen - 1;
        for (i=0; i < imax; ++i)
    	{
            if (b->ziffern[i] == 0)
    		{
                j++;
            }
    		else break;
        }
    
    	imax = b->laenge - j;
        for (i=0; i < imax; ++i)
    	{
            b->ziffern[i] = b->ziffern[i+j];
        }
    
    	b->laenge -= j;
    
    	/* Nachlaufende Nachkomma-Nullen eliminieren */
    	imin = b->laenge - b->nachkommastellen;
    	for (i = b->laenge - 1; i >= imin; --i)
    	{
            if (b->ziffern[i] == 0)
    		{
    			--b->nachkommastellen;
    			--b->laenge;
    		}
    		else break;
    	}
    
        return b;
    }
    
    /* Testziffern */
    #define Z0 {0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0} /* 0.0 */
    #define Z1 {0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0} /* 0.2 (n=10)*/
    #define Z2 {0,0,0,0,0,5, 2,0,0,0,0,0,0,0,0,0} /* 5.2 (n=10)*/
    #define Z3 {0,0,0,0,0,5, 0,0,0,0,0,0,0,0,0,0} /* 5.0 (n=10)*/
    #define Z4 {0,0,0,5,0,5, 0,0,0,0,0,0,0,0,0,0} /* 505.0 (n=10)*/
    #define Z5 {0,0,0,5,0,5, 2,0,2,0,0,0,0,0,0,0} /* 505.202 (n=10)*/
    #define Z6 {2,3,4,0,6,0, 0,8,9,0,1,3,5,7,9,2} /* 234060.0890135792 (n=10)*/
    
    unsigned char testziffern[] = Z5;   /* hier Z0, Z1, Z2... einsetzen */
    
    int main( void )
    {
        unsigned int i;
    
        struct bcd_number bcd =	{ sizeof(testziffern), 10, -1, testziffern };
    
        clean_bcd(&bcd);
    
        printf ("bcd.laenge:           %u\n",bcd.laenge);
        printf ("bcd.nachkommastellen: %u\n",bcd.nachkommastellen);
        printf ("bcd.vorzeichen:       %i\n",bcd.vorzeichen);
        printf ("bcd.ziffern:          ");
        for (i=0; i<bcd.laenge; ++i) printf ("%i ",bcd.ziffern[i]);
        puts ("\n");
    
        return 0;
    }
    

    Wenn Du noch IDE/Compiler/Betriebssystem angeben würdest, dann könnte man Tipps zum Debuggen geben. Debuggen zu können ist so wichtig wie programmieren zu können.

    viele grüße
    ralph



  • Debuggen zu können ist so wichtig wie programmieren zu können.

    Ich würde fast behaupten, es ist noch wichtiger. Leider kann ichs auch nicht per Debugger 🤡



  • rkhb schrieb:

    Wenn Du noch IDE/Compiler/Betriebssystem angeben würdest, dann könnte man Tipps zum Debuggen geben. Debuggen zu können ist so wichtig wie programmieren zu können.

    Also ich benutze den qt creator auf mac os. Debuggen ist mir jetzt völlig neu. In meinem C Buch wird es auch nicht erwähnt. Kennt ihr eine Quelle wo man sich einlesen kann?



  • Siegfried101 schrieb:

    Also ich benutze den qt creator auf mac os.

    Aaarghhh, kalt erwischt: MacOS habe ich nicht. Und der QT-Creator-Debugger zickt auf meinem WinXP. Naja:

    1. Du hast in QT-Creator eine Hilfe-Funktion: Entweder links ein Icon oder oben: Hilfe-Inhalt. Nun im Fenster "Inhalt" (linksoben) "QT Creator Manual 2- Debugging and...-Debugging" klicken (Auswahl öffnet sich mit Klick auf das Plus-Zeichen). Viel Spaß bei der englischen Lektüre.

    2. Lade mal mein "Prüfprogramm" oben und lasse es kompilieren. Nun gehst Du mit dem Cursor in die Zeile 9 ( j++; ) und drückst auf F9. Damit hast Du einen Breakpoint (Haltepunkt) gesetzt. Du siehst einen roten Punkt an der linken Seite. Als nächstes drückst Du auf F5 (oder klickst oben auf Debuggen-Debuggen-Debuggen). Nach einer kleinen Weile stoppt das Programm und der Cursor blinkt Dich von Zeile 9 an. Im Fenster rechts daneben siehst Du, welche Werte die lokalen Variablen im Augenblick haben. Du kannst dort weitere Ausdrücke überwachen lassen, z.B: Rechtsklick in diesem Fenster, "Neuen Ausdruck einfügen", "b->ziffern[i]" eingeben. Nun kannst Du im "Einzelschritt" (immer nur eine Zeile per Tastendruck) mit F10 die Schleife durchgehen. Du siehst, wie sich die Werte für i, j und b->ziffern[i] verändern. Um hier einen eventuellen Fehler zu entdecken, musst Du Dir natürlich völlig im Klaren sein, was in der aktuellen Zeile passieren soll.

    3. Wenn Du dasselbe mit Deiner nicht funktionierenden clean_bcd -Funktion machst, wirst Du merken, dass Du Dich schnell in einer Endlosschleife befindest. Du weißt also schon mal, wo ein Fehler ist. Dann kannst Du Dir überlegen: Was tun?

    4. Ein Haltepunkt wird mit einem erneuten Druck auf F9 wieder gelöscht. Das nennt sich "Toggeln" oder "Umschalten". Haltepunkte kann man an jeder Zeile setzen, wo man einen Stop wünscht. Du kannst nach einem Stop das Programm auch mit F5 wieder anlaufen lassen, es hält dann wieder an, wenn es auf einen Haltepunkt stößt.

    viele grüße
    ralph



  • rkhb schrieb:

    Aaarghhh, kalt erwischt: MacOS habe ich nicht. Und der QT-Creator-Debugger zickt auf meinem WinXP. Naja:

    1. Du hast in QT-Creator eine Hilfe-Funktion: Entweder links ein Icon oder oben: Hilfe-Inhalt. Nun im Fenster "Inhalt" (linksoben) "QT Creator Manual 2- Debugging and...-Debugging" klicken (Auswahl öffnet sich mit Klick auf das Plus-Zeichen). Viel Spaß bei der englischen Lektüre.

    2. Lade mal mein "Prüfprogramm" oben und lasse es kompilieren. Nun gehst Du mit dem Cursor in die Zeile 9 ( j++; ) und drückst auf F9. Damit hast Du einen Breakpoint (Haltepunkt) gesetzt. Du siehst einen roten Punkt an der linken Seite. Als nächstes drückst Du auf F5 (oder klickst oben auf Debuggen-Debuggen-Debuggen). Nach einer kleinen Weile stoppt das Programm und der Cursor blinkt Dich von Zeile 9 an. Im Fenster rechts daneben siehst Du, welche Werte die lokalen Variablen im Augenblick haben. Du kannst dort weitere Ausdrücke überwachen lassen, z.B: Rechtsklick in diesem Fenster, "Neuen Ausdruck einfügen", "b->ziffern[i]" eingeben. Nun kannst Du im "Einzelschritt" (immer nur eine Zeile per Tastendruck) mit F10 die Schleife durchgehen. Du siehst, wie sich die Werte für i, j und b->ziffern[i] verändern. Um hier einen eventuellen Fehler zu entdecken, musst Du Dir natürlich völlig im Klaren sein, was in der aktuellen Zeile passieren soll.

    3. Wenn Du dasselbe mit Deiner nicht funktionierenden clean_bcd -Funktion machst, wirst Du merken, dass Du Dich schnell in einer Endlosschleife befindest. Du weißt also schon mal, wo ein Fehler ist. Dann kannst Du Dir überlegen: Was tun?

    4. Ein Haltepunkt wird mit einem erneuten Druck auf F9 wieder gelöscht. Das nennt sich "Toggeln" oder "Umschalten". Haltepunkte kann man an jeder Zeile setzen, wo man einen Stop wünscht. Du kannst nach einem Stop das Programm auch mit F5 wieder anlaufen lassen, es hält dann wieder an, wenn es auf einen Haltepunkt stößt.

    viele grüße
    ralph

    Besten Dank Ralph! Man muss sich daran erstmal gewöhnen, aber mit bisschen Routine ist das wohl eine sehr große Hilfe.

    Ich bastel hier an noch einer Funktion mit der ich zwei BCD-Codes addiere.

    struct bcd_number *addition(struct bcd_number *a, struct bcd_number *b){
    
        int maxkomma,minkomma,maxlaenge,minlaenge,i,k,m;
        struct bcd_number *c;
    
        if ((a->nachkommastellen > b->nachkommastellen) || (a->nachkommastellen == b->nachkommastellen)) {
            maxkomma = a->nachkommastellen;
            minkomma = b->nachkommastellen;
        }
        else
            maxkomma = b->nachkommastellen;
            minkomma = a->nachkommastellen;
    
        if ((a->laenge > b->laenge) || (a->laenge == b->laenge)) {
            maxlaenge = a->laenge;
            minlaenge = b->laenge;
        }
        else
            maxlaenge = b->laenge;
            minlaenge = a->laenge;
    
        k = (minlaenge-maxlaenge)+(maxkomma-minkomma);
        m = maxlaenge+k;
    
        for (i=0; i<m; i++) {
            if ((a->laenge > b->laenge) || (a->laenge == b->laenge))  {
    
                c->ziffern[m-i]=a->ziffern[maxlaenge-1-i]+b->ziffern[maxlaenge-1+i+k];
            }
    
            else c->ziffern[m-i]=b->ziffern[maxlaenge-1-i]+a->ziffern[maxlaenge-1+i+k];
    
            if (c->ziffern[maxlaenge - 1 -i] > 9) {
                c->ziffern[maxlaenge - 1 -i] = c->ziffern[maxlaenge - 1 -i] % 10;
                c->ziffern[maxlaenge - 2 -i] += c->ziffern[maxlaenge - 1 -i] / 10;
            }
        }
        c->nachkommastellen=maxkomma;
    
        return c;
    }
    

    Es wird zwar fehlerfrei combiliert, aber leider werden keine Ergebnisse angezeigt. Eine Endlosschleife wird's diesmal nicht sein.

    Ist das Prinzip nach dem ich hier vorgegangen bin vertretbar? Oder bin ich völlig auf dem Holzweg?



  • Initialisierung von c fehlt.



  • Bashar schrieb:

    Initialisierung von c fehlt.

    Oh Danke. Mit was für Werten sollte man c vorzugsweise initialisieren?



  • So wie bei string2bcd.



  • Siegfried101 schrieb:

    Ich bastel hier an noch einer Funktion mit der ich zwei BCD-Codes addiere.

    Ich habe mir die Funktion nur oberflächlich angeschaut und mir fällt auf,
    dass der Index der Ziffern (z.B.: b->ziffern[maxlaenge-1+i+k]) zu groß werden kann.
    Male Dir das Ganze mal auf Papier auf:

    0.406
    + 2340.6091
         1  1
    ===========
      2341.0151
    

    Du siehst, dass an einigen Stellen eine Zahl gar keine Ziffern hat. Diese Fälle musst Du irgendwie abfedern.

    Hier was zum Knobeln, falls Dir das Silvester-Fernsehprogramm zu langweilig ist:

    #include <stdio.h>
    #include <stdlib.h>
    
    struct bcd_number
    {
        unsigned int laenge;
        unsigned int nachkommastellen;
        signed char vorzeichen;
        unsigned char *ziffern;
    };
    
    struct bcd_number* addition (struct bcd_number *a, struct bcd_number *b)
    {
        unsigned int i;
        int pad_a, pad_b;
        unsigned char* az, * bz, * cz;
        unsigned char aa, bb, cc, ue;
    
        /* Stichwort: ternärer Operator */
        unsigned int max_nachkomma = (a->nachkommastellen > b->nachkommastellen) ? a->nachkommastellen : b->nachkommastellen;
        unsigned int max_vorkomma = (a->laenge - a->nachkommastellen > b->laenge - b->nachkommastellen) ? a->laenge - a->nachkommastellen : b->laenge - b->nachkommastellen;
    
        struct bcd_number* c = malloc (sizeof (struct bcd_number)); /* free() nicht vergessen! */
        c->laenge = max_vorkomma + max_nachkomma;
        c->nachkommastellen = max_nachkomma;
        c->vorzeichen = +1;                                         /* provisorisch */
        c->ziffern = malloc (c->laenge);                            /* free() nicht vergessen! */
    
        pad_a = max_nachkomma - a->nachkommastellen;    /* "Keine Nachkommastelle"-Indikator */
        pad_b = max_nachkomma - b->nachkommastellen;    /* "Keine Nachkommastelle"-Indikator */
        az = a->ziffern + a->laenge - 1;                /* auf letzte Ziffer zeigen */
        bz = b->ziffern + b->laenge - 1;                /* auf letzte Ziffer zeigen */
        cz = c->ziffern + c->laenge - 1;                /* auf letzte Ziffer zeigen */
        ue = 0;                                         /* Übertrag */
    
        for (i = max_nachkomma + max_vorkomma; i > 0; --i)
        {
            aa = (pad_a-- > 0 || az < a->ziffern) ? 0 : *az--;   /* 1. Fall: Keine Nachkommastelle, 2. Fall: Keine Vorkommastelle */
            bb = (pad_b-- > 0 || bz < b->ziffern) ? 0 : *bz--;
            cc = aa + bb + ue;
            if (cc > 9) { ue = 1; cc -= 10; } else ue = 0;
            *cz-- = cc;
        }
    
        return c;
    }
    
    struct bcd_number * clean_bcd(struct bcd_number *b)
    {
        unsigned int i, j, imax, imin;
        imax = b->laenge - b->nachkommastellen - 1;
        for (j=0; j < imax && !b->ziffern[j]; ++j);
        imax = b->laenge - j;
        for (i=0; i < imax; ++i) b->ziffern[i] = b->ziffern[i+j];
        b->laenge -= j;
        imin = b->laenge - b->nachkommastellen;
        for (i = b->laenge - 1; i >= imin && !b->ziffern[i]; --i, --b->nachkommastellen, --b->laenge);
        return b;
    }
    
    /* Testziffern */
    #define Z0 {0,0,0,0,0,0, 4,0,6,0,0,0,0,0,0,0} /* 0.406 (n=10)*/
    #define Z1 {0,0,2,3,4,0, 6,0,9,1,0,0,0,0,0,0} /* 2340.609 (n=10)*/
    unsigned char testziffern1[] = Z0;
    unsigned char testziffern2[] = Z1;
    
    int main( void )
    {
        unsigned int i;
    
        struct bcd_number a = { sizeof(testziffern1), 10, +1, testziffern1 };
        struct bcd_number b = { sizeof(testziffern2), 10, +1, testziffern2 };
        struct bcd_number* c;
    
        clean_bcd(&a);
        clean_bcd(&b);
    
        puts ("     l |   n |  v  |  z");
        puts ("-----------------------------------------------------");
        printf ("a  %3u | %3u | %2i  |  ", a.laenge, a.nachkommastellen, a.vorzeichen);
        for (i=0; i<a.laenge; ++i) printf ("%i ",a.ziffern[i]); puts ("");
        printf ("b  %3u | %3u | %2i  |  ", b.laenge, b.nachkommastellen, b.vorzeichen);
        for (i=0; i<b.laenge; ++i) printf ("%i ",b.ziffern[i]); puts ("");
    
        c = addition (&a, &b);
    
        printf ("c  %3u | %3u | %2i  |  ", c->laenge, c->nachkommastellen, c->vorzeichen);
        for (i=0; i<c->laenge; ++i) printf ("%i ",c->ziffern[i]); puts ("");
    
        free (c->ziffern);
        free (c);
    
        return 0;
    }
    

    Guten Rutsch!

    viele grüße
    ralph



  • Danke Ralph!
    Ich habe deinen Code jetzt so umgeschrieben, dass ich eine Subtraktion durchführe. Jedoch funktioniert dies nicht falls das 2. Argument der Funktion größer ist als das 1.
    Kann man in der Funktion die Werte a->ziffern und b->ziffern miteinander tauschen?

    struct bcd_number* subtraktion (struct bcd_number *a, struct bcd_number *b)
    {
        unsigned int i;
        int pad_a, pad_b;
        unsigned char* az, * bz, * cz;
        unsigned char aa, bb, cc, ue, ueh=0;
    
        unsigned int max_nachkomma = (a->nachkommastellen > b->nachkommastellen) ? a->nachkommastellen : b->nachkommastellen;
        unsigned int max_vorkomma = (a->laenge - a->nachkommastellen > b->laenge - b->nachkommastellen) ? a->laenge - a->nachkommastellen : b->laenge - b->nachkommastellen;
    
        struct bcd_number* c = malloc (sizeof (struct bcd_number)); 
        c->laenge = max_vorkomma + max_nachkomma;
        c->nachkommastellen = max_nachkomma;
        c->vorzeichen = +1;                                        
        c->ziffern = malloc (c->laenge);                            
    
        pad_a = max_nachkomma - a->nachkommastellen;    
        pad_b = max_nachkomma - b->nachkommastellen;    
        az = a->ziffern + a->laenge - 1;               
        bz = b->ziffern + b->laenge - 1;               
        cz = c->ziffern + c->laenge - 1;                
        ue = 0;                                         
    
    /*Hier a->ziffern und b->ziffern vertauschen, falls b->ziffern > a->ziffern?*/
    
        for (i = max_nachkomma + max_vorkomma; i > 0; --i)
        {
            aa = (pad_a-- > 0 || az < a->ziffern) ? 0 : *az--;   
            bb = (pad_b-- > 0 || bz < b->ziffern) ? 0 : *bz--;
    
            if (aa < bb){
                aa += 10;
                ueh = 1;
            }
    
            cc = aa - bb - ue;
    
            if (ueh == 1) {
                ue = 1;
            }
            else ue = 0;
    
            *cz-- = cc;
        }
        return c;
    }
    

    Bei Funktionen für Multiplikation und Division bleibt der Code bis Zeile 23 im großen und ganzen derselbe oder?
    Kann man für den Übertrag, bei der Multiplikation, Modulo benutzen? Ich bin mir nämlich nicht sicher, ob das bei char geht.



  • Siegfried101 schrieb:

    Danke Ralph!
    Ich habe deinen Code jetzt so umgeschrieben, dass ich eine Subtraktion durchführe. Jedoch funktioniert dies nicht falls das 2. Argument der Funktion größer ist als das 1.
    Kann man in der Funktion die Werte a->ziffern und b->ziffern miteinander tauschen?

    Mööönsch, mach doch was ich geraten habe: Auf dem Papier ausprobieren!
    Nein, Du kannst einzelne Ziffern nicht tauschen und alle Ziffern zu tauschen, ist recht mühselig und wirkt sich auf die übergebenen Zahlen
    aus (Stichwort: Call By Reference). Es ist aber möglch, lokal (Stichwort: Call By Value) ganze Zahlen zu tauschen.
    Nachfolgend ein Beispiel für den einfachsten Fall, dass beide Zahlen positiv
    sind und die zweite Zahl mehr Vorkommaziffern hat:

    #include <stdio.h>
    #include <stdlib.h>
    
    struct bcd_number
    {
        unsigned int laenge;
        unsigned int nachkommastellen;
        signed char vorzeichen;
        unsigned char *ziffern;
    };
    
    struct bcd_number* subtraktion (struct bcd_number* a, struct bcd_number* b)
    {
        unsigned int i;
        int pad_a, pad_b;
        unsigned char* az, * bz, * cz;
        unsigned char aa, bb, cc, ue;
    	struct bcd_number* x;
    
        /* Stichwort: ternärer Operator */
        unsigned int max_nachkomma = (a->nachkommastellen > b->nachkommastellen) ? a->nachkommastellen : b->nachkommastellen;
        unsigned int max_vorkomma = (a->laenge - a->nachkommastellen > b->laenge - b->nachkommastellen) ? a->laenge - a->nachkommastellen : b->laenge - b->nachkommastellen;
    
        struct bcd_number* c = malloc (sizeof (struct bcd_number)); /* free() nicht vergessen! */
        c->laenge = max_vorkomma + max_nachkomma;
        c->nachkommastellen = max_nachkomma;
        c->vorzeichen = +1;                                         /* provisorisch */
        c->ziffern = malloc (c->laenge);                            /* free() nicht vergessen! */
    
    	if (a->laenge - a->nachkommastellen < b->laenge - b->nachkommastellen)
    	{
    		x = a;
    		a = b;
    		b = x;
    		c->vorzeichen = -1;
    	}
    
        pad_a = max_nachkomma - a->nachkommastellen;    /* "Keine Nachkommastelle"-Indikator */
        pad_b = max_nachkomma - b->nachkommastellen;    /* "Keine Nachkommastelle"-Indikator */
        az = a->ziffern + a->laenge - 1;                /* auf letzte Ziffer zeigen */
        bz = b->ziffern + b->laenge - 1;                /* auf letzte Ziffer zeigen */
        cz = c->ziffern + c->laenge - 1;                /* auf letzte Ziffer zeigen */
        ue = 0;                                         /* Übertrag */
    
        for (i = max_nachkomma + max_vorkomma; i > 0; --i)
        {
            aa = (pad_a-- > 0 || az < a->ziffern) ? 0 : *az--;
            bb = (pad_b-- > 0 || bz < b->ziffern) ? 0 : *bz--;
    		if ((aa-bb-ue) < 0)
    		{
    			cc = aa + 10 - bb - ue;
    			ue = 1;
    		}
    		else
    		{
    			cc = aa - bb - ue;
    			ue = 0;
    		}
            *cz-- = cc;
        }
    
        return c;
    }
    
    struct bcd_number * clean_bcd(struct bcd_number *b)
    {
        unsigned int i, j, imax, imin;
        imax = b->laenge - b->nachkommastellen - 1;
        for (j=0; j < imax && !b->ziffern[j]; ++j);
        imax = b->laenge - j;
        for (i=0; i < imax; ++i) b->ziffern[i] = b->ziffern[i+j];
        b->laenge -= j;
        imin = b->laenge - b->nachkommastellen;
        for (i = b->laenge - 1; i >= imin && !b->ziffern[i]; --i, --b->nachkommastellen, --b->laenge);
        return b;
    }
    
    /* Testziffern */
    #define Z0 {0,0,0,0,0,0, 4,0,6,0,0,0,0,0,0,0} /* 0.406 (n=10)*/
    #define Z1 {0,0,2,3,4,0, 6,0,9,1,0,0,0,0,0,0} /* 2340.6091 (n=10)*/
    unsigned char testziffern1[] = Z0;
    unsigned char testziffern2[] = Z1;
    
    int main( void )
    {
        unsigned int i;
    
        struct bcd_number a = { sizeof(testziffern1), 10, +1, testziffern1 };
        struct bcd_number b = { sizeof(testziffern2), 10, +1, testziffern2 };
        struct bcd_number* c;
    
        clean_bcd(&a);
        clean_bcd(&b);
    
        puts ("     l |   n |  v  |  z");
        puts ("-----------------------------------------------------");
        printf ("a  %3u | %3u | %2i  |  ", a.laenge, a.nachkommastellen, a.vorzeichen);
        for (i=0; i<a.laenge; ++i) printf ("%i ",a.ziffern[i]); puts ("");
        printf ("b  %3u | %3u | %2i  |  ", b.laenge, b.nachkommastellen, b.vorzeichen);
        for (i=0; i<b.laenge; ++i) printf ("%i ",b.ziffern[i]); puts ("");
    
        c = subtraktion (&a, &b);
    
        printf ("c  %3u | %3u | %2i  |  ", c->laenge, c->nachkommastellen, c->vorzeichen);
        for (i=0; i<c->laenge; ++i) printf ("%i ",c->ziffern[i]); puts ("");
    
        free (c->ziffern);
        free (c);
    
        return 0;
    }
    

    Bei Funktionen für Multiplikation und Division bleibt der Code bis Zeile 23 im großen und ganzen derselbe oder?
    Kann man für den Übertrag, bei der Multiplikation, Modulo benutzen? Ich bin mir nämlich nicht sicher, ob das bei char geht.

    Ja und ja. Jetzt reift bei mir aber der Verdacht, dass es sich nicht mehr
    um eine gemeine Weihnachtsaufgabe handelt, sondern um eine Semesteraufgabe
    mit Benotung. Da musst Du jetzt aber mal selbst in die Gänge kommen 🕶

    viele grüße
    ralph



  • Ich wollte noch hinzufügen, dass sogar die Addition nicht korrekt ausgeführt wird. Es wird gar nicht das Vorzeichen der Zahlen beachtet, weil -a+b ist ungleich a+b. Nur als kleine Anmerkung...



  • Franzi42 schrieb:

    Ich wollte noch hinzufügen, dass sogar die Addition nicht korrekt ausgeführt wird. Es wird gar nicht das Vorzeichen der Zahlen beachtet, weil -a+b ist ungleich a+b. Nur als kleine Anmerkung...

    Ja danke ich weiß. Da hab ich für den Fall der Fälle die Subtraktions-Funktion drin.



  • Muss leider genau die gleiche Aufgabe machen und leider sagen, dass die Subtraktion bei mir auch nicht Reibungsfrei läuft, wenn die Zahlen unterschiedliche Längen haben. Ich gebs aber jetzt auf. 👎


Anmelden zum Antworten