Problem: Ziffernweise Division



  • Bei mir hängst ärger bei der Ziffernweise Division.
    Die Funktion zur Division lautet void div(const int *z1, const int *z2, int *erg, int *rest, int lang), zur schnelleren Orientierung. Ich komm einfach nicht dahinter wo das Problem steckt... Die Subtraktion stimmt, setzFeldNull passt auch, ausgabe stimmt auch... div sollte eigentlich auch stimmen... Kanns sein das er vllt. einen Fehler bekommt weil ich ihm 2x die selbe Adresse in sub übergebe, 1x const und 1x normal?
    mfG Terrasearch

    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <ctype.h>
    #define LAENGE 60
    
    int isIntFeld(const char *ein);
    void setzFeldNull(int *feld, int lang);
    int speichereWert(const char *ch, int *zahl, int lang);
    void ausgabe(const int *zahl, int lang);
    void add(const int *z1, const int *z2, int *erg, int lang);
    void sub(const int *z1, const int *z2, int *erg, int lang);
    void mul(const int *z1, const int *z2, int *erg, int lang);
    void div(const int *z1, const int *z2, int *erg, int *rest, int lang);
    int a_gleich_b(const int *z1, const int *z2, int lang);
    void hilfe();
    int Menu(char *ch,int *zahl1,int *zahl2,int *ergebnis,int *rest,int lang);
    
    int main(){
      int zahl1[LAENGE], zahl2[LAENGE], ergebnis[LAENGE*2], rest[LAENGE];
      char ch[LAENGE+1]="";
    
      hilfe();
      Menu(ch,zahl1,zahl2,ergebnis,rest,LAENGE);
    
      printf("Druecken sie eine beliebige Taste um das Programm zu beenden...");
      getch();
      return 0;
    }//main
    
    int isIntFeld(const char *ein){
      int i;
      for(i=0;ein[i]!='\0';i++)
        if(!isdigit(ein[i]))
          return 0;
      return 1;
    }//isZahl ende
    
    void setzFeldNull(int *feld, int lang){
      int i;
      for(i=0;i<lang;i++)
        feld[i]=0;
    }//setzAufNull ende
    
    int speichereWert(const char *ch, int *zahl, int lang){
      int i;
      for(i=0;ch[i]!='\0';i++)
        zahl[lang-strlen(ch)+i]=ch[i]-'0';
    }//speichereWert ende
    
    void ausgabe(const int *zahl, int lang){
      int i,j;
      for(i=0;zahl[i]=='\0'&&i<lang;i++)
        ;
      for(j=0;i<lang;i++,j++)
        printf("%d",zahl[i]);
      if(j==0)
        putchar('0');
    }//ausgabe ende
    
    void add(const int *z1, const int *z2, int *erg, int lang){
      int i;
      for(i=lang-1;i>=0;i--){
        erg[i]+=z1[i]+z2[i];
        if(erg[i]>9){
          erg[i-1]+=1;
          erg[i]-=10;
        }
      }
    }//add ende
    
    void sub(const int *z1, const int *z2, int *erg, int lang){
      int i, h=a_gleich_b(z1,z2,lang);
      if(h>0){
        for(i=lang-1;i>=0;i--){
          erg[i]+=z1[i]-z2[i];
          if(erg[i]<0){
            erg[i-1]-=1;
            erg[i]+=10;
          }
        }
      }  
      if(h<0){
        for(i=lang-1;i>=0;i--){
          erg[i]+=z2[i]-z1[i];
          if(erg[i]<0){
            erg[i-1]-=1;
            erg[i]+=10;
          }
        }
      for(i=0;erg[i]=='\0'&&i<lang;i++)
        ;
      erg[i]*=-1;
      }
    }//sub ende
    
    void mul(const int *z1, const int *z2, int *erg, int lang){
      int i,j,k,l,hilf;
      for(i=0;z1[i]=='\0'&&i<lang;i++)
        ;
      for(j=0;z2[j]=='\0'&&i<lang;j++)
        ;
      for(k=i;k<lang;k++)
        for(l=j;l<lang;l++)
          erg[k+l+1]+=z1[k]*z2[l];
      for(i=lang*2;i>0;i--){
        hilf=erg[i]/10;
        erg[i-1]+=hilf;
        erg[i]-=hilf*10;
      }
    }//mul ende
    
    void div(const int *z1, const int *z2, int *erg, int*rest, int lang){
      int i,j;
      for(i=0;i<lang;i++){
        rest[lang-1]=z1[i];
        while(a_gleich_b(rest,z2,lang)>0){
          sub(rest,z2,rest,lang);
          erg[i]++;
        }
        for(j=1;j<lang;j++)
          rest[j-1]=rest[j];
      }
    }//div ende
    
    int a_gleich_b(const int *z1, const int *z2, int lang){
      int i, hilf=0;
      for(i=0;i<lang&&hilf==0;i++){
        hilf=z1[i]-z2[i];
      }
      return hilf;
    }//a_glecih_b ende
    
    void hilfe(){
      system("cls");
      printf("%40s","Hilfe\n\n\n");
      printf("Dies ist ein 60-stelliger Taschenrechner.\n");
      printf("Im Menue koennen Sie zwischen 4 verschiedenen Rechenoperationen "); 
      printf("waehlen.\n"); 
      printf("Haben Sie sich fuer einen Operator korrekt entschieden, "); 
      printf("koennen Sie zwei \npositive bis zu 60-stellige Zahlen eingeben.\n");
      printf("Zum Schluss werden Sie aufgefordert sich zu entscheiden ob Sie"); 
      printf(" nochmals mit dem\nselben Rechenoperator arbeiten wollen, ");
      printf("in das Menue wechseln wollen,\noder das Programm beenden wollen.\n");
      printf("\nDruecken Sie eine beliebige Taste um in das Menue zu wechseln.");
      getch();
      system("cls");
    }
    
    int Menu(char *ch,int *zahl1,int *zahl2,int *ergebnis,int *rest,int lang){
      int i;
      char c,c2;
      do{
        printf("Welche Rechnung moechten Sie durchfuehren?\n");
        printf("(1)Addition\n");
        printf("(2)Subtraktion\n");
        printf("(3)Multiplikation\n");
        printf("(4)Division - noch in Bearbeitung\n");
        printf("(5)Hilfe\n");
        printf("(0)Ende\n");
        printf("< >\b\b");
        i=0;
        do{
          if(i)
            printf("\b\b< > Falsche Eingabe\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
          c=getche();
          i=1;
        }while(c<'0'||c>'5');
    
        system("cls");
    
        if(c!='5'&&c!='0'){
          do{
            setzFeldNull(zahl1,LAENGE);
            setzFeldNull(zahl2,LAENGE);
            setzFeldNull(ergebnis,LAENGE*2);
            setzFeldNull(rest,LAENGE);
            switch(c){
              case '1':printf("%35s\n","Addition");
                       break;
              case '2':printf("%35s\n","Subtraktion");
                       break;
              case '3':printf("%35s\n","Multiplikation");
                       break;
              case '4':printf("%35s\n","Division");
                       break;
            }
            do{
              printf("\nGeben Sie die erste Zahl ein\n");
              gets(ch);
            }while(!isIntFeld(ch));
            speichereWert(ch,zahl1,lang);
    
            do{
              printf("\nGeben Sie die zweite Zahl ein\n");
              gets(ch);
            }while(!isIntFeld(ch));
            speichereWert(ch,zahl2,lang);
    
            switch(c){
              case '1':add(zahl1,zahl2,ergebnis,lang);
                       break;
              case '2':sub(zahl1,zahl2,ergebnis,lang);
                       break;
              case '3':mul(zahl1,zahl2,ergebnis,lang);
                       break;
              case '4':div(zahl1,zahl2,ergebnis,rest,lang);
            }
            printf("\nErgebnis:\n");
            if(c=='3')
              ausgabe(ergebnis,lang*2);
            else
              ausgabe(ergebnis,lang);
            if(c=='4'){
              printf("\nRest:\n");
              ausgabe(rest,lang);
            }
            printf("\n\nWollen Sie den Vorgang wiederholen?");
            printf("\n(1)Ja");
            printf("\n(2)Menue");
            printf("\n(3)Hilfe");
            printf("\n(0)Ende\n");
            printf("< >\b\b");
            i=0;
            do{
              if(i)
                printf("\b\b< > Falsche Eingabe\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
              c2=getche();
              i=1;
            }while(c2<'0'||c2>'3');
            system("cls");
          }while(c2=='1');
        }
        if(c=='5'||c2=='3')
          hilfe();
      }while(c!='0'&&c2!='0');
    }
    




  • okay, nochmal, gaaaanz langsam.
    Ich versuche einen Taschenrechner zu machen, dieser soll bis zu 60 stellige Zahlen Addieren, Subrahieren, Multiplizieren und Dividieren können. Diese Zahlen speichere ich Ziffernweise in Arrays (zahl1[60]), in der Form:
    0000000000000000000000000...01234=1234
    00000000000000000000000...0233333=233333
    Addition, Subtraktion und Multiplikation haben super funktioniert. Aber die Division funzt ned. Ich will das in dem System machen:
    1234:2
    Ich nehme die vorderste Stelle, das ist also eine null, weil sie ja wie oben abgespeichert sind und überprüfe ob sie größer der zu Dividierende Zahl ist.
    Dadurch das 0 kleiner 2 ist, geht er zur nächsten Ziffer, diese eine Null ist, usw.

    Bis er zur 1 kommt. Er speichert dies mal in Rest.
    0000...01
    Dies ist aber noch immer kleiner 2. Also weiter.
    Wir kommen zu 2. Jetzt muss mal der Rest verschoben werden.
    0000...010
    Jetzt wird rest[lang-1]=2 gesetzt.
    0000...012
    Jetzt ist sie größer als 2. Also wird solange subtrahiert und ergebniss[derzeitige Stelle der 1. Zahl]++ gemacht, bis sie wieder kleiner der zu dividierende Zahl ist. Also:
    0000...012

    0000...002
    __________ erg: 0000...0100
    0000...010

    0000...002
    __________ erg: 0000...0200
    0000...008
    usw.

    Und das ganze wird wieder wiederholt. Die Subtraktion funktioniert. Die Division sollte funzen. Aber es tut nicht, Beim Rest kommt ein Blödsinn raus, beim Ergebnis ebenfalls, alle Zahlen sind korrekt, alles initialisiert...
    Aber schaut selbst:

    void div(const int *z1, const int *z2, int *erg, int*rest, int lang){
      int i,j;
      for(i=0;i<lang;i++){
        rest[lang-1]=z1[i];
        while(a_gleich_b(rest,z2,lang)>0){
          sub(rest,z2,rest,lang);
          erg[i]++;
        }
        for(j=1;j<lang;j++)
          rest[j-1]=rest[j];
      }
    }//div ende
    

    Das ist die Funktion Division. Sie verwendet 2 weitere Funktionen:

    void sub(const int *z1, const int *z2, int *erg, int lang){
      int i, h=a_gleich_b(z1,z2,lang);
      if(h>0){
        for(i=lang-1;i>=0;i--){
          erg[i]+=z1[i]-z2[i];
          if(erg[i]<0){
            erg[i-1]-=1;
            erg[i]+=10;
          }
        }
      }  
      if(h<0){
        for(i=lang-1;i>=0;i--){
          erg[i]+=z2[i]-z1[i];
          if(erg[i]<0){
            erg[i-1]-=1;
            erg[i]+=10;
          }
        }
      for(i=0;erg[i]=='\0'&&i<lang;i++)
        ;
      erg[i]*=-1;
      }
    }//sub ende
    

    und

    int a_gleich_b(const int *z1, const int *z2, int lang){
      int i, hilf=0;
      for(i=0;i<lang&&hilf==0;i++){
        hilf=z1[i]-z2[i];
      }
      return hilf;
    }//a_gleich_b ende
    

    sub ist für die Subtraktion zuständig. Sie sollte tadellos funktionieren, ich hab sie ausführlich getestet.
    a_gleich_b schaut welches Feld größer ist. Sie gibt eine einstellige positive Zahl zurück wenn z1 größer z2, 0 wenn sie gleich sind und eine einstellige negative Zahl zurück wenn z1 kleiner z2 ist.
    Ich hab echt schon keine Ahnung mehr wo der Fehler ist... Aber schaut selbst...



  • Hier als Beispiel:

    Division
    
    Geben Sie die erste Zahl ein
    2123412
    
    Geben Sie die zweite Zahl ein
    123
    
    Ergebnis:
    6130100
    Rest:
    -2147483636-2147483564-2147483636-2147483564-2147483636-2147483564-2147483636-21
    47483564-2147483636-2147483564-2147483636-2147483564-2147483636-2147483564-21474
    83636-2147483564-2147483636-2147483564-2147483636-2147483564-2147483636-21474835
    64-2147483636-2147483564-2147483636-2147483564-2147483636-2147483564-2147483636-
    2147483564-2147483636-2147483564-2147483636-2147483564-2147483636-2147483564-214
    7483636-2147483564-2147483636-2147483564-2147483636-2147483564-2147483636-214748
    3564-2147483636-2147483564-2147483636-2147483564-2147483636-2147483564-214748363
    6-10737417261073741742-214748358876345122
    
    Wollen Sie den Vorgang wiederholen?
    (1)Ja
    (2)Menue
    (3)Hilfe
    (0)Ende
    < >
    

    Ach ja, kleine Bemerkung: isdigit ist ein Befehl von ctype.h

    return a nonzero (true) result if it satisfies the following conditions. If not, then 0 (false) is returned.
    int isdigit(int character);
    isdigit a digit (0 to 9)



  • in div() lass dir nach jedem schritt alle aenderungen ausgeben.



  • Fehler gefunden.
    Ich hab die Variable Rest problematischer Weise so bearbeitet in der Subtraktion das da immer eine andere Zahl subtrahiert wird, dadurch hab ich dann eine zweier potenz erhalten, diese verursacht hat, das ich int overflow hatte...


Anmelden zum Antworten