Thomas Kramer

IT-COW | Februar 2011

C-Aufgaben: Lösung einer quadratischen Gleichung

By Administrator at Februar 08, 2011 20:43
Filed Under: C(++), Programmierung allgemein, Studium

Eine weitere C-Aufgabe war das vollständige Lösen einer quadratischen Gleichung. Gemäß Wikipedia ist die Ursprungsform einer quadratischen Gleichung

 

ax^2 + bx + c = 0

 

Eine solche Gleichung überführt man in die sogenannte Normalform, indem man a/a, b/a und c/a teilt. Die Normalform sieht anschließend so aus:

 

x^2 + px + q = 0

 

wobei p=b/a entspricht und q=c/a. Anschließend kann die Gleichung mithilfe der bekannten pq-Formel berechnet werden, siehe Wikipedia.

 

In der Aufgabenstellung wurde aber nicht die pq-Formel auf die Normalform angewandt, sondern die Stammform der pq-Formel auf die Ursprungsform der quadratischen Gleichung. Diese sieht folgendermaßen aus:

 

x1,2 = 1/2a * (-b +/- sqrt(b^2-4*a*c))

 

Wie man sieht gibt es hier noch die drei Variablen a, b und c und nicht nur zwei wie bei der pq-Formel, weil sie eben nicht auf die Normalform der Gleichung angewandt werden muss.

 

Je nach Ausgangswerte der Variablen a, b und c wird dann nach zehn Berechnungsvorschriften unterschieden... In dem Quellcode sind ein paar Beispielberechnungen mit Ausgaben enthalten, gemäß der Aufgabenstellung.

 

Eine Ergänzung zu den komplexen Zahlen, diese werden allgemein in einen reellen und einen imaginären Teil aufgesplittet. Ich zitiere: (Quelle: Link)

 

"Komplexe Zahlen sind Zahlen der Form z = x + iy wobei x und y reelle Zahlen sind. Die komplexen Zahlen stellen eine Erweiterung der reellen Zahlenmenge dar. Die imaginäre Einheit i genügt der Gleichung i2 = –1. Daher gilt für die imaginäre Einheit i = (–1)½. Ist z = x + iy, so ist Re(z) = x der Realteil und Im(z) = y der Imaginärteil der komplexen Zahl z. Achtung: Nicht iy ist der Imaginärteil der komplexen Zahl z, sondern nur die reelle Zahl y."

 

Nachfolgend mein Quellcode. Die C-Funktion (f)abs() liefert übrigens den Betrag einer Zahl zurück - immer einen positiven Wert.

 

*
 * =============================================================
 *
 *       Filename:  7.1.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created: 
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Thomas Kramer
 *        Company:  
 *
 * =============================================================
 */

#include    <stdlib.h>
#include    <stdio.h>
#include  <math.h>
#include  <ctype.h>
#include  <time.h>
#include  <assert.h>

#define TRIVIALE_LOESUNG        0
#define WIDERSPRUCH             1
#define EINE_REELLE_LOESUNG     2
#define ZWEI_REELLE_LOESUNGEN   3
#define ZWEI_KOMPLEXE_LOESUNGEN 4

#define TEST_OK      1
#define TEST_FAILURE 0
const double SCHRANKE = 1E-10;

int loese_quad_gleich(double a, double b, double c, double *x1, double *x2);
void gib_aus(double x1, double x2, int typ);
int kontrolle (double a, double b, double c, double x1, double x2, int typ);

int main ( )
{
  int tests = 9;
  double testdata[9][3] = {
    {-2, -26, -44},
    {0.0, 2.0,  0.0},
    {0.0, 7.2,  2.4},
    {7.0, 0.0,  0.0},
    {2.4, 0.0, -6.0},
    {2.4, 0.0,  6.0},
    {7.1, 9.2,  0.0},
    {4.1, 5.2, -6.3},   
    {4.1, 5.2,  6.3}   
  };
  double a=0;
  double b=0;
  double c=0;
  double x1=0;
  double x2=0;
  int typ=0;

  int i;

  for (i=0; i<tests; i++){
    a=testdata[i][0];
    b=testdata[i][1];
    c=testdata[i][2];
        printf("-------------------------------------------------------------");
    printf("\nNeue Aufgabe \n");
      printf("-------------------------------------------------------------");
        printf("\na=%5.1lf, b=%5.1lf, c=%5.1lf ", a, b, c);
    typ=loese_quad_gleich(a, b, c, &x1, &x2);
    gib_aus(x1, x2, typ);
    if (kontrolle(a, b, c, x1, x2, typ) == TEST_FAILURE)
    {
      printf("\n=> Kontrolle falsch!\n");
    } else {
      printf("\n=> Kontrolle richtig!\n");
    }
  }

    return 0;
}               


/*  ===  FUNCTION  =========================================================
 *         Name:  loese_quad_gleich
 *  Description:  Löse quadratische Gleichungen über 10 Fälle
 *
 *  Rückgabewerte:
 *  siehe defines am Anfang
 * =====================================================================
 */
int loese_quad_gleich(double a, double b, double c, double *x1, double *x2)
{
    double u=0;
    double v=0;
    //    double i=0;
    int fall=0;
    int typ = 0;

    /* ----- Fallnummer berechnen ----- */
    if (a!=0.0) fall+=4;
    if (b!=0.0) fall+=2;
    if (c!=0.0) fall+=1;

    *x1=0;
    *x2=0;

    switch (fall)
    {
        case 0:
            typ = TRIVIALE_LOESUNG;
            break;
        case 1:
            typ = WIDERSPRUCH;
            break;
        case 2:
            typ = EINE_REELLE_LOESUNG;
            break;
        case 3:
            *x1=-c/b;
            typ = EINE_REELLE_LOESUNG;
            break;
        case 4:
            typ = ZWEI_REELLE_LOESUNGEN;
            break;
        case 5:
            u=-c/a;
            if (u>=0)
            {
                // Fall 5.1
                // pos. zahl von wurzel u
                *x1=sqrt(u);
                // neg. zahl von wurzel u
                *x2=-(sqrt(u));
                typ = ZWEI_REELLE_LOESUNGEN;
            } else {
                // Fall 5.2        
                // Realteil der komplexen Zahl (x1) gibt es hier nicht oder ist Null, weil
                // keine Addition stattfindet
                //
                // i kann natürlich nicht berechnet werden, nur als Info wofür es steht
                // i=sqrt(-1);

                *x1=0;
                // durch Negation wird hier aus u eine positive zahl, nur dann ist
                // auch wurzelziehen möglich
                *x2=sqrt(-u);
                typ = ZWEI_KOMPLEXE_LOESUNGEN;
            }
            break;
        case 6:
            *x2=-b/a;
            typ = ZWEI_REELLE_LOESUNGEN;
            break;
        case 7:
            v=(b*b)-(4*a*c);
            // i kann natürlich nicht berechnet werden, nur als Info wofür es steht
            // i=sqrt(-1);

            if (v>=0)
            {
                // Fall 7.1
                *x1=(1/(2*a)) * (-b + sqrt(v));
                *x2=(1/(2*a)) * (-b - sqrt(v));
                typ = ZWEI_REELLE_LOESUNGEN;
            } else {
                // Fall 7.2
                *x1=-b;
                // durch Negation wird hier aus v eine positive zahl,  nur dann ist
                // auch wurzelziehen möglich
                *x2=sqrt(-v);
                typ = ZWEI_KOMPLEXE_LOESUNGEN;
            }
    }
    return typ;
}

/*  ===  FUNCTION  =========================================================
 *         Name:  gib_aus
 *  Description:  gibt Typ der Gleichung und Ergebnisse aus
 * =====================================================================
 */
void gib_aus(double x1, double x2, int typ)
{
    printf("\n");
    switch (typ)
    {
        case TRIVIALE_LOESUNG:
            printf("triviale Gleichung \n");
            break;
        case WIDERSPRUCH:
            printf("Widerspruch \n");
            break;
        case EINE_REELLE_LOESUNG:
            printf("eine reelle Lösung \n");
            if (x1!=0)
            {
              printf("\nx1=%lf", x1);
        } else {
              printf("\nx2=%lf", x2);    
        }
            break;
        case ZWEI_REELLE_LOESUNGEN:
            printf("zwei reelle Lösungen \n");
            printf("\nx1=%lf, x2=%lf", x1, x2);
            break;
        case ZWEI_KOMPLEXE_LOESUNGEN:
            printf("zwei komplexe Lösungen \n");
            printf("\nx1=%lf, x2=%lf", x1, x2);
            break;
    }
}

/*  ===  FUNCTION  =========================================================
 *         Name:  kontrolle
 *  Description:  Kontrollrechnung ausführen, wenns stimmt 1=true zurückgeben,  ansonsten 0=false
 * =====================================================================
 */
int kontrolle (double a, double b, double c, double x1, double x2, int typ)
{
  int result = TEST_FAILURE;

    double r = x1;
    double s = x2;
    
    switch (typ)
    {
        case TRIVIALE_LOESUNG:
            result = TEST_OK;
            break;
        case WIDERSPRUCH:
            result = TEST_OK;
            break;
        case EINE_REELLE_LOESUNG:
            if (fabs(a*(x1*x1)+b*x1+c)<=SCHRANKE)
            {
                result = TEST_OK;
            }
            break;
        case ZWEI_REELLE_LOESUNGEN:
            if ((fabs(a*(x1*x1)+b*x1+c)<=SCHRANKE) && (fabs(a*(x2*x2)+b*x2+c)<=SCHRANKE))
            {
              result = TEST_OK;
            }
          break;
        case ZWEI_KOMPLEXE_LOESUNGEN:
          if (fabs((a*(r*r-s*s)+(b*r)+c)<=SCHRANKE) && (fabs(a*(2*r*s)+(b*s))<=SCHRANKE))
            {
              result = TEST_OK;
            }
            break;
        default:
      printf("Ungültiger Typ %d\n",  typ);
      exit(EXIT_FAILURE);    
    }
    return result;
}

 

Tag-Wolke

Monats-Liste