staging.inyokaproject.org

Probleme bei der Umsetzung eines weiteren C Programms

Status: Ungelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

ElDuderinooo

Anmeldungsdatum:
17. Dezember 2017

Beiträge: 5

Hallo liebe Gemeinde!

Ich habe nun verscuht ein weiteres C Programm zu schreiben. Dabei sollen die Ableitungen von Polynomen nten Grades (wobei n ⇐ 10) gebildet werden. Das Ganze soll über einen rekursiven Funktionsaufruf geschehen. Das Programm lässt sich ebenfalls kompilieren und ist lauffähig, allerdings versemmelt es mir die Ausgabe der Ableitung. Ich finde den Fehler leider nicht und weiß auch ehrlich gesagt nicht an werlchem Schräubchen ich drehen könnte, so dass es mir die richtige Ausgabe erzeugt. Falls jemand gnädigerweise etwas Zeit über hat und einen Blick drauf werfen könnte, wäre ich sehr dankbar ☺...

Hier der Quellcode:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
#include <stdio.h>

void ableitung(int a[11], int a_strich[11], int k)
{
  for(int i = 11; i >= 0; i--)      // Feld durchlaufen und Bildung der Ableitungskoeff.
  {
    a_strich[i - 1] = a[i] * i;
  }

  if(k > 0)  
  {
    ableitung(a_strich, a, k - 1);      // rekursiver Aufruf -> Bildung der erneuten Abl. der Abl.
  }
}

int main (void)
{
  int n;        // Variablen deklarieren
  int max_koeff;
  int new_koeff;
  
  int a[11];        // benoetigte Felder initialisieren
  int a_strich[11];
  
  // Werte der Felder auf 0 setzen
  
  for(int i = 0; i <= 11; i++)
  {
    a[i] = 0;
  }
  
  for(int i = 0; i <= 11; i++)
  {
    a_strich[i] = 0;
  }
  
  printf("Bitte den Grad n des einzulesenden Polynoms angeben (0 <= n <= 10).\n");
  scanf("%d", &n);
  
  for(int i = 0; i <= n; i++)       // einlesen der Koeffizienten
  {
    printf("Bitte den Koeffizienten a%d eingeben: \n", i);
    scanf("%d", &a[i]);
  }
  
  printf("P(x) =");
  
  for(int i = n; i >= 0; i--)       // Erzeugen der Ausgabe der eingelesenen Gesamtfunktion
  {
    if(a[i] != 0)
    {
      if(i > 1)
      {
        printf(" %d*x^%d +", a[i],i);
      }
      else if(i == 1)
      {
        printf(" %d*x +", a[1]);
      }
      else
      {
        printf(" %d\n", a[0]);
      }
    }
  }
  
  printf("Die wievielte Ableitung von P soll bestimmt werden?\n");
  scanf("%d", &max_koeff);
  
  new_koeff = max_koeff;        // Hilfsvariable
  
  ableitung(a, a_strich, new_koeff);        // Aufruf der Ableitungsfkt.
  
  printf("P");
  
  for(int i = 1; i <= max_koeff; i++)       // Notation des Ableitungsgrades
  {
      printf("’");
  }
  
  printf("(x) = ");
  
  for(int i = n; i >= 0; i--)       // Erzeugen der Ausgabe der abgeleiteten Funktion
  {
    if(a_strich[i] != 0)
    {
      if(i > 1)
      {
        printf(" %d*x^%d +", a_strich[i],i);
      }
      else if(i == 1)
      {
        printf(" %d*x +", a_strich[1]);
      }
      else
      {
        printf(" %d\n", a_strich[0]);
      }
    }
  }
  
  printf("\n");
  
  return 0;
}

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@ElDuderinooo: „[A]llerdings versemmelt es mir die Ausgabe der Ableitung“ ist keine sinnvolle Fehlerbeschreibung. Was gibtst Du ein, was erwartest Du daraufhin als Ausgabe, und was bekommst Du stattdessen, und warum glaubst Du das sollte nicht so sein?

Die Rekursion ist unsinnig, die solltest Du loswerden. Bei Programmiersprachen ohne garantierte „tail call optimization“ sollte man simple for- oder while-Schleifen nicht durch Rekursion ersetzen.

Die 11 kommt zu oft als „magische Zahl“ im Quelltext vor — mach daraus eine Konstante am Programmanfang die man dort dann auch zentral einmal ändern kann, wenn man mehr oder weniger Koeffizienten braucht.

Der Code zur Ausgabe eine Polynoms wiederholt sich zweimal im Code, das verletzt das „DRY“-Prinzip („Don't Repeat Yourself“) und gehört in eine Funktion.

Was ist der Sinn von new_koeff? Warum nicht einfach max_koeff verwenden?

Kommentare sollten erklären warum etwas so gemacht wird, wie es gemacht wird, und nicht was gemacht wird. Sofern das „warum“ nicht offensichtlich ist. Denn was gemacht wird, steht da ja schon als Code. Kommentare wie // Variablen deklarieren oder // Aufruf der Ableitungsfkt. bringen dem Leser Null mehrwert, der Programmierer muss aber immer darauf achten das solche Kommentare auch bei/nach Änderungen immer noch stimmen.

Edit: Was auf jeden Fall falsch ist: Das Ergebnis landet nicht immer in a_strich.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

Mal ein Versuch meinerseits mit einem Polynomial-Verbunddatentyp und einer Ableitungsfunktion die ”in place” arbeitet. Ausserdem gibt es keine Beschränkung auf 11 Koeffizienten.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int max_exponent;
    int *coeffs;
} Polynomial;


void Polynomial_init(Polynomial *p, int max_exponent)
{
    int i;
    
    p->max_exponent = max_exponent;
    if (max_exponent >= 0) {
        p->coeffs = malloc((max_exponent + 1) * sizeof(p->coeffs[0]));
        for (i = 0; i <= max_exponent; ++i) p->coeffs[i] = 0;
    } else {
        p->coeffs = NULL;
    }
}

void Polynomial_destroy(Polynomial *p)
{
    p->max_exponent = -1;
    if (p->coeffs) {
        free(p->coeffs);
        p->coeffs = NULL;
    }
}

void Polynomial_print(Polynomial *p, unsigned int derive_count)
{
    int i, coeff;
    bool first;
    
    putchar('P');
    for (i = 0; i < (int) derive_count; ++i) putchar('\'');
    printf("(x) = ");
    
    first = true;
    for (i = p->max_exponent; i >= 0; --i) {
        coeff = p->coeffs[i];
        if (coeff) {
            if (!first) printf(" + "); else first = false;
            printf("%d", coeff);
            if (i > 0) {
                printf("*x");
                if (i > 1) printf("^%d", i);
            }
        }
    }
    if (first) putchar('0');
    putchar('\n');
}

void Polynomial_derive(Polynomial *p)
{
    int i;
    
    if (p->max_exponent < 0) return;
    
    for (i = 1; i <= p->max_exponent; ++i) p->coeffs[i - 1] = p->coeffs[i] * i;
    p->coeffs[p->max_exponent] = 0;
}


int main(void)
{
    Polynomial p;
    unsigned int degree, derive_count;
    unsigned int i;
    
    puts("Bitte den Grad n des einzulesenden Polynoms angeben.");
    scanf("%u", &degree);
    Polynomial_init(&p, degree);

    for (i = 0; i <= degree; ++i) {
        printf("Bitte den Koeffizienten a_%d eingeben.\n", i);
        scanf("%d", &p.coeffs[i]);
    }
    Polynomial_print(&p, 0);

    puts("Die wievielte Ableitung von P soll bestimmt werden?");
    scanf("%u", &derive_count);
    
    for (i = 1; i <= derive_count; ++i) {
        Polynomial_derive(&p);
        Polynomial_print(&p, i);
    }

    Polynomial_destroy(&p);
    return 0;
}

Testlauf:

Bitte den Grad n des einzulesenden Polynoms angeben.
4
Bitte den Koeffizienten a_0 eingeben.
1
Bitte den Koeffizienten a_1 eingeben.
2
Bitte den Koeffizienten a_2 eingeben.
3
Bitte den Koeffizienten a_3 eingeben.
4
Bitte den Koeffizienten a_4 eingeben.
5
P(x) = 5*x^4 + 4*x^3 + 3*x^2 + 2*x + 1
Die wievielte Ableitung von P soll bestimmt werden?
5
P'(x) = 20*x^3 + 12*x^2 + 6*x + 2
P''(x) = 60*x^2 + 24*x + 6
P'''(x) = 120*x + 24
P''''(x) = 120
P'''''(x) = 0

ElDuderinooo

(Themenstarter)

Anmeldungsdatum:
17. Dezember 2017

Beiträge: 5

Wow, da ziehe ich den Hut! Die Umsetzung sieht wirklich sehr professionell aus. Verstehe den Quellcode zwar an einigen Stellen nicht so ganz, aber werde mich die Tage mal näher damit befassen, um das Ganze entsprechend nachvollziehen zu können. Vielen vielen Dank.

Und die Umsetzung über eine rekursive Funktion macht deiner Meinung nach keinen Sinn?

Antworten |