Statistik



  • Ich mache gerade meine ersten Schritte in C. Dazu folgender Code:

    #include <stdio.h>
    #include <math.h>
    
    float varianz_berechnen(int *daten)
    {
        float summe = 0;
        for (int i = 0; i <= sizeof(daten); i++) {
            summe += (daten[i] - mittelwert_berechnen(daten)) * (daten[i] - mittelwert_berechnen(daten));
        }
        return summe / sizeof(daten);
    }
    
    float standardabweichung_berechnen(int *daten)
    {
        return sqrt(varianz_berechnen(daten));
    }
    
    float spannweite_berechnen(int *daten)
    {
        int max = 0;
        int min = 10000000;
        for (int i = 0; i <= sizeof(daten); i++) {
            if (daten[i] > max)
                max = daten[i];
            if (daten[i] < min)
                min = daten[i];
        }
        return max - min;
    }
    
    float mittelwert_berechnen(int *daten)
    {
        float summe_der_elemente = 0;
        for (int i = 0; i <= sizeof(daten); i++) {
            summe_der_elemente += daten[i];
        }
        return summe_der_elemente / sizeof(daten);
    }
    
    float median_berechnen(int *daten)
    {
        int laenge = sizeof(daten);
        if (laenge % 2 == 0) {
            return (daten[laenge/2] + daten[laenge-1]) / 2.0;
        } else {
            return daten[laenge/2];
        }
    }
    
    // float modalwert_berechnen(int *daten){}
    
    int main(int argc, const char * argv[])
    {
        int daten[] = {2, 4, 5, 6, 8, 9, 14, 16};
    //  printf("Modalwert: %.2f\n", modalwert_berechen(daten));
        printf("Median: %.2f\n", median_berechnen(daten));
        printf("Mittelwert: %.2f\n", mittelwert_berechnen(daten));
        printf("Spannweite: %.2f\n", spannweite_berechnen(daten));
        printf("Standardabweichung: %.2f\n", standardabweichung_berechnen(daten));
        printf("Varianz: %.2f\n", varianz_berechnen(daten));
        return 0;
    }
    

    Ich habe die Fehlermeldung: Conflicting types for 'mittelwert_berechnen'. Was mache ich falsch?

    P.S: Der Modalwert ist auskommentiert, weil ich noch nicht weiß, wie ich das mache 😃

    Falls es hilft: Ich versuche gerade meinen Ruby-Code umzusetzen:

    class Statistik
      def initialize(daten)
        @daten = daten.sort 
      end
    
      def varianz_berechnen
        s = 0
        @daten.each { |x| s+= (x - mittelwert_berechnen)**2 }
        s / @daten.length
      end
    
      def standardabweichung_berechnen
        Math.sqrt(self.varianz_berechnen)
      end
    
      def median_berechnen
        l = @daten.length
        l % 2 == 0 ? (@daten[l/2] + @daten[l-1]) / 2.0 : @daten[l/2]
      end
    
      def modalwert_berechnen
        @daten.group_by { |x| x }.values.max_by(&:size).first
      end
    
      def mittelwert_berechnen
        @daten.inject(:+) / @daten.length
      end
    
      def spannweite_berechnen
        @daten.max - @daten.min
      end 
    end
    

    Sorry, kein Ruby-Highlighting 😞



  • In C solltest du Funktionen vor der Verwendung deklarieren. Aus historischen Gründen werden Funktionen implizit deklariert, jedoch mit int (und eben nicht float) als Rückgabedatentyp!

    Und:
    Dein sizeof(daten); berechnet die Größe eines Zeigers, nicht des Arrays. Die Arraygröße muss daher z.B. als zusätzliches Argument übergeben werden.


  • Mod

    Du hast die Funktion mittelwert_berechnen benutzt, bevor du sie deklariert hast (Erste Benutzung in Zeile 8, Deklaration (und Definition) in Zeile 31). Vereinfacht gesagt geht ein C-Compiler den Code bloß ein einziges Mal von oben nach unten durch. Dummerweise gibt es aber aus historischen Gründen eine recht fehlerlastige Regel, was passiert, wenn er dabei auf eine unbekannte Funktion trifft: Er denkt sich in dem Fall anhand der Benutzung einfach aus, welche Signatur zu der Funktion am ehesten passt.
    Hier schließt er in Zeile 8, dass mittelwert_berechnen wohl die Signatur

    int mittelwert_berechnen(int*);
    

    haben sollte. Der Rückgabewert int ist in diesem Fall einfach die Standardvorgabe.

    Wenn er aber in Zeile 31 ankommt, sieht er einen Konflikt mit der dortigen Deklaration

    float mittelwert_berechnen(int*);
    

    . Daher Fehler.

    Abhilfe:
    a) Funktionen in die richtige Reihenfolge bringen
    oder
    b) Die Funktionen vorher deklarieren, zum Beispiel vor Zeile 4 noch ein

    float mittelwert_berechnen(int* daten);
    

    einfügen. Und wenn du das so machst, dann am besten auch gleich für alle deine Funktionen. Ausblick: Später wirst du diesen Teil mit den ganzen Deklarationen dann in eine Headerdatei schreiben.



  • Wow, das ist wirklich nervig 😃 Habe die Größe des Arrays jetzt mit

    int laenge = sizeof(daten) / sizeof(daten[0]);
    

    bestimmt. Stimmt das so?



  • SeppJ schrieb:

    Du hast die Funktion mittelwert_berechnen benutzt, bevor du sie deklariert hast (Erste Benutzung in Zeile 8, Deklaration (und Definition) in Zeile 31). Vereinfacht gesagt geht ein C-Compiler den Code bloß ein einziges Mal von oben nach unten durch. Dummerweise gibt es aber aus historischen Gründen eine recht fehlerlastige Regel, was passiert, wenn er dabei auf eine unbekannte Funktion trifft: Er denkt sich in dem Fall anhand der Benutzung einfach aus, welche Signatur zu der Funktion am ehesten passt.
    Hier schließt er in Zeile 8, dass mittelwert_berechnen wohl die Signatur

    int mittelwert_berechnen(int*);
    

    haben sollte. Der Rückgabewert int ist in diesem Fall einfach die Standardvorgabe.

    Ist das wirklich so? Ich dachte der macht daraus immer:

    int mittelwert_berechnen()
    

    Also immer int als Rückgabetyp und eine undefinierte(?) Anzahl an Parametern.

    Bin nur neugierig...

    Gruß
    Matze



  • kaenon schrieb:

    Wow, das ist wirklich nervig 😃

    C ist ja auch keine Kindergartensprache.

    kaenon schrieb:

    Habe die Größe des Arrays jetzt mit

    int laenge = sizeof(daten) / sizeof(daten[0]);
    

    bestimmt. Stimmt das so?

    Ja.
    Allerdings nur da, wo du daten auch als Array definiert hast.
    Bei dir in main .



  • kaenon schrieb:

    float spannweite_berechnen(int *daten)
    {
        int max = 0;
        int min = 10000000;
    

    Diese Vorbelegeung ist ungünstig.
    Besser wäre zumindest INT_MIN bzw INT_MAX aus limits.h

    Es gibt aber einen Wert, der für beide richtig ist und auch ganz sicher Teil des Arrays ist:

    Das Erste Element vom Array



  • MatzeHHC schrieb:

    Ist das wirklich so? Ich dachte der macht daraus immer:

    int mittelwert_berechnen()
    

    Ja, inklusive Argumentpromotion (was das ganze noch schlimmer macht).

    Siehe http://port70.net/~nsz/c/c89/c89-draft.html#3.3.2.2.

    Und wenn du GCC verwendest, kannst du -Wformat missbrauchen um den Typ einer Variable (halbwegs verlässlich) zu erfahren: http://goo.gl/Y78KKl.



  • kaenon schrieb:

    Ich habe die Fehlermeldung: Conflicting types for 'mittelwert_berechnen'. Was mache ich falsch?

    Ab C99 sind implzite Funktionsdeklarationen nicht mehr erlaubt.
    Bei gcc hilft dir

    gcc -std=c99 -pedantic -Werror
    

    dabei; hier wird dann nur compiliert, wenn du nicht gegen C99 verstößt, d.h. du musst erst alle Warnungen=Fehler beseitigen.



  • Habe es wie folgt geändert:

    #include <stdio.h>
    #include <math.h>
    
    float varianz_berechnen(int *daten, int laenge);
    float standardabweichung_berechnen(int *daten, int laenge);
    float spannweite_berechnen(int *daten, int laenge);
    float mittelwert_berechnen(int* daten, int laenge);
    float median_berechnen(int *daten, int laenge);
    
    int main(int argc, const char * argv[])
    {
        int daten[] = {2, 4, 5, 6, 8, 9, 14, 16};
        int laenge = sizeof(daten) / sizeof(daten[0]);
    
        printf("Varianz: %.2f\n", varianz_berechnen(daten, laenge));
        printf("Standardabweichung: %.2f\n", standardabweichung_berechnen(daten, laenge));
        printf("Spannweite: %.2f\n", spannweite_berechnen(daten, laenge));
        printf("Mittelwert: %.2f\n", mittelwert_berechnen(daten, laenge));
        printf("Median: %.2f\n", median_berechnen(daten, laenge));
    
        return 0;
    }
    
    float varianz_berechnen(int *daten, int laenge)
    {
        float summe = 0;
        for (int i = 0; i <= laenge; i++) {
            summe += powf(daten[i] - mittelwert_berechnen(daten, laenge), 2);
        }
        return summe / laenge;
    }
    
    float standardabweichung_berechnen(int *daten, int laenge)
    {
        return sqrt(varianz_berechnen(daten, laenge));
    }
    
    float spannweite_berechnen(int *daten, int laenge)
    {
        int max = 0;
        int min = 10000000;
        for (int i = 0; i <= laenge; i++) {
            if (daten[i] > max)
                max = daten[i];
            if (daten[i] < min)
                min = daten[i];
        }
        return max - min;
    }
    
    float mittelwert_berechnen(int *daten, int laenge)
    {
        float summe_der_elemente = 0;
        for (int i = 0; i <= laenge; i++) {
            summe_der_elemente += daten[i];
        }
        return summe_der_elemente / laenge;
    }
    
    float median_berechnen(int *daten, int laenge)
    {
        if (laenge % 2 == 0) {
            return (daten[laenge/2] + daten[laenge-1]) / 2.0;
        } else {
            return daten[laenge/2];
        }
    }
    

    Der erste Fehler ist die Spannweite, das Minimum beträgt komischerweise 0 und nicht 2. Hat das was damit:

    Es gibt aber einen Wert, der für beide richtig ist und auch ganz sicher Teil des Arrays ist: Das Erste Element vom Array

    zu tun?

    Der zweite Fehler liegt in Varianz und Standardabweichung, da stimmen die Ergebnisse nicht 😞



  • for (int i = 0; i <= laenge; i++)
    

    Klassischer Anfängerfehler, Arrayindexe gehen immer von 0...N-1, bei dir aber von 0...N, und UB ist das dann auch noch.



  • Das hat das Problem gelöst, danke. Wo gibt es eigentlich gute C-Tutorials? Und was lagere ich jetzt wie in ein Header-File? Und sollte ich C oder lieber doch C++ lernen?



  • kaenon schrieb:

    Wo gibt es eigentlich gute C-Tutorials?

    In Büchereien.
    Die haben so viele davon, dass sie diese sogar verkaufen.
    (Aber nicht jedes dort ist gut)



  • Fehlerfreie C Tutorials gibt es sehr selten.
    Alle Funktionsprototypen (explizite Funktionsdeklarationen) gehören in eine Headerdatei, ebenso wie eigene Typdefinitionen (typedef).
    C oder C++, das hängt von deinem Aufgabenbereich ab; C geht sehr viel mehr in die Tiefe, es gibt mehr Fallstricke. Das liegt daran, dass C von Profis für Profis entwickelt wurde, was auf C++ nicht zutrifft. C ist also prinzipiell nichts für Anfänger, die nur schnell eben mal was programieren wollen/sollen.



  • Also ist für den schnellen Erfolg C++ besser geeignet?



  • Deshalb habe ich gesagt "hängt ab von deinem Aufgabenbereich";
    wenn es dir nur darum geht, mal schnell irgendwelche Strings zusammenzubasteln oder mit cout irgendwas auf die Konsole zu bringen, wird es mit C++ schneller gehen, dann aber bitte nicht jammern wenn du merkst, dass dieses Geraffel oftmals viel mehr Code erfordert als sscanf/sprintf.
    Wenn du darauf angewiesen bist, bestehende C-Bibliotheken zu benutzen (WinAPI, u.v.a.m), hast du von vornherein verloren, wenn du nur mit C++ Brille diese Bibliotheken versuchst zu bedienen, bspw. den Unterschied zw. Array und Zeiger oder automatic/static storage duration nicht kennst.


  • Mod

    kaenon schrieb:

    Also ist für den schnellen Erfolg C++ besser geeignet?

    Nein, C++ ist eher noch weniger für Anfänger geeignet. Man sagt: "In C ist es leicht, sich selber in den Fuß zu schießen. In C++ ist es schwerer, aber wenn man es tut, dann ist gleich das ganze Bein ab". Diese Beschreibung trifft es ziemlich gut. In C++ musst du nicht kämpfen, um ein paar popelige Ausgaben zu machen oder Zeichenketten zu verarbeiten. Aber die Sprache ist ungleich umfangreicher als C. Man kann C komplett in ein paar Tagen bis Wochen lernen. Für C++ muss man ein paar Monate einplanen. Ganz zu schweigen von weiterer Lernzeit, um zu lernen, wie man "gutes" C++ schreibt (was allerdings auch in C der Fall ist), denn bloß weil etwas geht, heißt das noch lange nicht, dass es eine gute Idee ist.

    Beide Sprachen sind nicht an Anfänger gerichtet, sondern an Profis. Wenn du damit Programmieren an sich lernen möchtest, dann mach dich darauf gefasst, dass das nicht ganz einfach wird (Ist aber möglich und haben schon viele Leute gemacht). Die Wahl der Sprache hängt davon ab, was man später damit machen möchte. C++ wird vor allem für Programme benutzt, bei denen hohe Rechenleistung eine Rolle spielt. C eigentlich auch, bloß dass es halt weniger mächtig ist. Ehrlich gesagt ist der einzige Grund, der mir einfällt, wieso man als Normalsterblicher heutzutage noch C brauchen könnte, dass es eine Menge C-Code auf der Welt gibt und man eventuell mit diesem arbeiten möchte.



  • Ehrlich gesagt ist der einzige Grund, der mir einfällt, wieso man als Normalsterblicher heutzutage noch C brauchen könnte, dass es eine Menge C-Code auf der Welt gibt und man eventuell mit diesem arbeiten möchte.

    Naja, ganz so ist es auch nicht glaub ich. Z.B.: Sind die gängigen Industrieroboter Programmiersprachen alle auf C basiert. Ok, Pointer wurden "zum glück" weggelassen 🙂



  • By the Way... Wer kennt ein wirklich gutes Tutorial für C++ ?? Die meisten sind ja eher unterirdisch.....


  • Mod

    weltmeiser_2014 schrieb:

    By the Way... Wer kennt ein wirklich gutes Tutorial für C++ ?? Die meisten sind ja eher unterirdisch.....

    Bis jetzt hat sich noch nie ein gutes Tutorial für C++ in diesem Forum gezeigt. Ich wäre eher überrascht, wenn plötzlich eines auftauchen würde. Ist ja auch nachvollziehbar: Wenn man sich hinreichend gut auskennt und es didaktisch drauf hat und den Wunsch verspürt, Anfängern zu helfen, dann schreibt man eher ein Buch, als ein Tutorial. Tutorials sind gut, um kurze Sachverhalte darzustellen. Für eine Sprache wie C++, bei deren Umfang selbst knappe(!) Anfängerbücher locker 1000 Seiten und mehr haben, ist das Medium eher ungeeignet. Es gibt ja auch keine (guten) Latein-Tutorials 😉 .



  • Wutz schrieb:

    Das liegt daran, dass C von Profis für Profis entwickelt wurde, was auf C++ nicht zutrifft.

    warum nicht?
    😕


Anmelden zum Antworten