Programm funktioniert für n = 20, aber für n = 50 nicht!



  • Hallo alle zusammen,

    ich habe ein Programm geschrieben (der erste Teil ist für die Binomfunktion) und habe folgendes Problem:
    - Für n = 20 funktioniert das Programm komplett.
    - Für n = 50 funktioniert er zum Teil.
    Er gibt dann "F ist 29" aus. Aber den Wert "W ist ..." gibt er gar nicht aus. Auch beendet er das Programm nicht. Ich habe jetzt schon etwas länger "gewartet" aber es kommt trotzdem kein Ergebnis raus. Nebenbei ist die Zahl für F richtig.
    - Selbiges gilt für n = 100 etc

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    int a; int b;
    int binom (int a, int b)
    {
        int tempA, tempB;
        if (( b == 0 ) || (a == b)){
            return 1;
        }
        else
        {
            tempA = binom (a - 1, b);
            tempB = binom (a - 1, b - 1);
            return tempA + tempB;
        }
    }
    
    int main()
    {
    float p;
    float q;
    float X0;
    int n;
    float e;
    float f;
    
    p = 0.6;
    q = 1-p;
    X0 = 10;
    n = 100;
    e = 1;
    f = 0.2;
    
    int S;
    int F;
    float a;
    float b;
    a = log(e) - log(X0) - n*log(1-f);
    b = log(1+f) - log(1-f);
    S = a/b;
    F = n - S;
    if(S < 0){
    return 1;
    }
    printf("F ist %d ", F);
    float W;
    W = 0;
    int i;
    for(i = F; i < n+1; i++){
        W = W + binom(n,i)*pow(p, n-i)*pow(q,i);
    }
    W = W*100;
    printf("W ist %f", W);
    return 0;
    }
    


  • nor mal geraten, ist da ein integer-überlauf schuld?


  • Mod

    Räum deinen Code auf, in der derzeitigen Form ist er unlesbar. Wahrscheinlich liegt da drin das Problem, da du selber nicht mehr durchblickst.
    Wie man Probleme nachstellbar und nachvollziehbar macht

    Der von volkard vermutete Integerüberlauf klingt aufgrund der Symptome wahrscheinlich, aber weder ich noch volkard werden den Code im derzeitigen Zustand genauer angucken.



  • Also ich habe mir das durchgelesen, habe versucht es zu verbessern. Aber ich weiß nicht, was ich alles weglassen darf. Da ich Anfänger bin schreibe ich im Code alles zu explizit. Ich habe es nun etwas verbessert. Wenn immer noch falsch, was kann ich denn explizit verbessern?

    #include <stdio.h>
    #include <stdlib.h>
    
    int a; int b;
    int binom (int a, int b)
    {
        int tempA, tempB;
        if (( b == 0 ) || (a == b)){
            return 1;
        }
        else
        {
            tempA = binom (a - 1, b);
            tempB = binom (a - 1, b - 1);
            return tempA + tempB;
        }
    }
    
    int main()
    {
        float p = 0.6;
        float q = 1-p;
        float X0 = 10;
        int n = 50;
        float e = 1;
        float f = 0.2;
        float a = log(e) - log(X0) - n*log(1-f);
        float b = log(1+f) - log(1-f);
        int S = a/b;
        int F = n - S;
        if(S < 0){
            return 1;
        }
        printf("F ist %d ", F);
        float W = 0;
    
        int i;
        for(i = F; i < n+1; i++){
            W = W + binom(n,i)*pow(p, n-i)*pow(q,i);
        }
        W = W*100;
        printf("W ist %f", W);
        return 0;
    }
    

    Ich weiß wirklich nicht, was ich sonst verbessern kann. Ich wäre euch dankbar, wenn ihr mir
    1.) Verbesserungsvorschläge explizit gebt
    2.) mir bei meinem Problem helfen könnt.

    Viele Grüße


  • Mod

    Zumindest mit der Einrückung der Initialisierung der Variablen ist das doch schon eine großer Fortschritt, findest du nicht? Wenn die Variablen jetzt noch aussagekräfitge Namen hätten; du über die Notwendigkeit der Variablen nachdenken würdest (was sollen beispielsweise die globalen a und b?); und du nur den zum Problem gehörigen Code zeigen würdest (das Problem ist doch nur die binom-Funktion und ihr Aufruf, oder? Was soll dann der Kram mit dem F davor?); dann wäre das nochmals ein großer Fortschritt.

    So zum Beispiel:

    #include <stdio.h>
    
    int binom (int a, int b)
    {
        int tempA, tempB;
        if (( b == 0 ) || (a == b)){
            return 1;
        }
        else
        {
            tempA = binom (a - 1, b);
            tempB = binom (a - 1, b - 1);
            return tempA + tempB;
        }
    }
    
    int main()
    {
      int i;
      for(i = 29; i < 51; i++){
        binom(50,i);
      }
      return 0;
    }
    

    Demonstriert immer noch den von dir beschriebenen Fehler, ist aber frei von unnötigen Ablenkungen. Oder, da du selber sicher schon festgestellt hast, dass bereits bei i==29 das Problem auftritt:

    int main()
    {
      binom(50,29);
      return 0;
    }
    

    All das sind Dinge, die du selber ganz leicht machen könntest, es kostet dich bloß etwas Zeit und Mühe. Du willst schließlich Hilfe, also komm doch denen, die dir helfen können und wollen möglichst weit entgegen.

    Mit so einem Programm kann ich arbeiten, ich melde mich, wenn ich den Fehler gefunden habe.


  • Mod

    Wenn ich das recht sehe, ist das Programm an sich fehlerfrei. Es läuft bloß furchtbar lang, da der Algorithmus ungünstig gewählt ist.

    Auch werden die Zwischenergebnisse bei diesen Werten irgendwann überlaufen, was aber keine Auswirkung auf die Laufzeit hat. Diese ist in jedem Fall ungeheuer groß.

    Effiziente Algorithmen (noch dazu ohne Probleme bezüglich der Zwischenergebnisse) zum Berechnen des Binomialkoeffizienten findest du auf Wikipedia oder in zahlreichen Threads hier im Forum. Beispielsweise dieser, der erst wenige Tage alt ist und sogar "Binomialkoeffizient" heißt:
    https://www.c-plusplus.net/forum/333411
    https://www.c-plusplus.net/forum/p2458666#2458666

    Das ist auch etwas, was man mit nur geringer Eigeninitiative selber hätte finden können.



  • Sehe ich das richtig dass binom in O(2a-b) läuft? 😮
    Dabei sieht das Ding auf den 1. Blick so harmlos aus. 🤡


  • Mod

    hustbaer schrieb:

    Sehe ich das richtig dass binom in O(2a-b) läuft? 😮
    Dabei sieht das Ding auf den 1. Blick so harmlos aus. 🤡

    Beides waren auch genau meine Gedanken, nachdem ich es mir näher angesehen hatte 😃



  • Hallo alle zusammen,

    ich habe jetzt den Binomialkoeffizienten selbst programmiert.
    Mit einer for Schleife. Dürfte ja nicht so schwer sein.
    Aber das Programm funktioniert nicht. Was mach ich falsch?

    #include <stdio.h>
    #include <stdlib.h>
    
    int binom (int a, int b){
        int i;
        int bin = 1;
        for(i=1; i<b+1; i++){
            bin = bin*(a-(i-1))/i;
        }
        return bin;
    }
    

    Als Meldung kommt
    "undefined reference to bin"

    Was habe ich denn diesmal falsch gemacht?


  • Mod



  • Es kommt die Fehlermeldung:
    "cannot open output file C:Users/..."

    Ich hatte zuerst nen Fehler drin, im zweiten Teil den ich nicht hier reinkopiert habe. Aber nach Verbesserung kam trotzdem diese "Fehlermeldung".


  • Mod

    Manchen Leuten kann man einfach nicht helfen.



  • Sorry,
    den letzten Beitrag habe ich geschrieben, ohne deinen zu lesen.
    Habe mich zuerst selbst zitiert etwas geschrieben, dann wieder gelöscht.
    Da ich keinen Account angemeldet habe, konnte ich den vorletzten Beitrag nicht editieren.

    Deswegen der neue Beitrag mit der anderen Fehlermeldung.

    Ich bin jetzt nicht so, dass ich keine Verbesserungsvorschläge annehme und mich nicht bemühe. Nur sind meine Kenntnisse halt schlecht, da alles so lange zurück liegt. Ich weiß z.B. nicht was für ein Fehlertyp das ist, den ich oben geschrieben habe.

    Ich habe die Regeln ja durchgelesen. Aber was bedeutet "Gib von vornherein an, welchen Compiler und welche IDE du benutzt". Welchen Compiler benutze ich denn und welche IDE. Wie finde ich das heraus?

    PS:
    Hatte meinen Accountnamen und PW vergessen, deswegen eher anonym geschrieben. Ich glaube ist jetzt besser mit dem Account zu schreiben, damit ich editieren etc kann.

    Edit:
    Es wäre auch besser einfach meinen Fehler zu sagen, und nicht einen Link zu geben. Ich mein z.B. "Wima du hast nicht angegeben, welchen Compiler du nutzt + Link", wäre für mich auch hilfreicher.



  • wima--09 schrieb:

    Hallo alle zusammen,

    ich habe jetzt den Binomialkoeffizienten selbst programmiert.
    Mit einer for Schleife. Dürfte ja nicht so schwer sein.
    Aber das Programm funktioniert nicht. Was mach ich falsch?

    #include <stdio.h>
    #include <stdlib.h>
    
    int binom (int a, int b){
        int i;
        int bin = 1;
        for(i=1; i<b+1; i++){
            bin = bin*(a-(i-1))/i;
        }
        return bin;
    }
    

    Als Meldung kommt
    "undefined reference to bin"

    Was habe ich denn diesmal falsch gemacht?

    Die meldung bedeutet dass bin undefiniert ist.

    Du musst bin entweder global machen, heißt du setzt ein

    int bin
    

    direkt nach include.

    Oder

    Du deklarierst es separat in der Funktion und der main.


  • Mod

    wima_carsi38 schrieb:

    Edit:
    Es wäre auch besser einfach meinen Fehler zu sagen, und nicht einen Link zu geben. Ich mein z.B. "Wima du hast nicht angegeben, welchen Compiler du nutzt + Link", wäre für mich auch hilfreicher.

    Der Code ist unvollständig und passt nicht zum Fehler. Was meinst du, warum ich sonst einen Link zu einem Beitrag gepostet habe, der erklärt, wie man vollständigen Code mit dazu passenden Fehlermeldungen erstellt? (Dein Problem fällt übrigens in die Kategorie "Linkerfehler")

    essios Analyse würde ich mich übrigens nur halb anschließen. Offensichtlich ist bin irgendwo nicht richtig definiert, aber die richtige Lösung ist sicher nicht, es einfach global zu definieren.



  • Edit siehe nächsten Beitrag



  • Hallo alle zusammen,

    Danke noch einmal für eure Hilfe.

    also ich habe das Programm von vorne geschrieben. Jetzt kommt keine Fehlermeldung.
    Wie gesagt schreibe ich ab jetzt mit dem Account, damit ich editieren kann.
    Das Problem mit "undefined reference to bin", hatte sich geklärt.
    Hat aber i-wie trotzdem nicht funktioniert.

    Jetzt ist das Problem, dass denke ich "int" nicht ausreicht.
    50 über x funktioniert bis x = 7. Ab x = 8 kommen "falsche" Zahlen raus. Ich denke, das liegt an der Speichergröße von "int". Aber "long int" oder auch "float" ändert nichts an der Tatsache.

    Der Code ist hier:

    #include <stdio.h>
    #include <stdlib.h>
    
    int binom (int a, int b){
        int i;
        int bin = 1;
        for(i=1; i<b+1; i++){
            bin = bin*(a-(i-1))/i;
        }
        return bin;
    }
    
    int main()
    {
        int c;
        c = binom(50,8);
        printf("c ist %d",c);
        return 0;
    }
    

    Und Sorry, dass ich als Anfänger viele Fehler auch bei der Problembeschreibung mache! Ich werde mich aber verbessern 🙂


  • Mod

    Manchmal muss es eben long long int sein.



  • SeppJ schrieb:

    essios Analyse würde ich mich übrigens nur halb anschließen. Offensichtlich ist bin irgendwo nicht richtig definiert, aber die richtige Lösung ist sicher nicht, es einfach global zu definieren.

    Damit war eig. die Deklaration gemeint und nicht die Definition.
    Die Definition muss man dann separat machen wie in der Funktion, sieht nämlich so aus als würde die main einen bin Wert bekommen der nur in der Funktion Deklariert ist.

    wima_carsi38 schrieb:

    Hallo alle zusammen,

    Danke noch einmal für eure Hilfe.

    also ich habe das Programm von vorne geschrieben. Jetzt kommt keine Fehlermeldung.
    Wie gesagt schreibe ich ab jetzt mit dem Account, damit ich editieren kann.
    Das Problem mit "undefined reference to bin", hatte sich geklärt.
    Hat aber i-wie trotzdem nicht funktioniert.

    Jetzt ist das Problem, dass denke ich "int" nicht ausreicht.
    50 über x funktioniert bis x = 7. Ab x = 8 kommen "falsche" Zahlen raus. Ich denke, das liegt an der Speichergröße von "int". Aber "long int" oder auch "float" ändert nichts an der Tatsache.

    Der Code ist hier:

    #include <stdio.h>
    #include <stdlib.h>
    
    int binom (int a, int b){
        int i;
        int bin = 1;
        for(i=1; i<b+1; i++){
            bin = bin*(a-(i-1))/i;
        }
        return bin;
    }
    
    int main()
    {
        int c;
        c = binom(50,8);
        printf("c ist %d",c);
        return 0;
    }
    

    Und Sorry, dass ich als Anfänger viele Fehler auch bei der Problembeschreibung mache! Ich werde mich aber verbessern 🙂

    Wenn sich durch double oder long int nichts ändert liegt es nicht an int.

    int main()
    {
        int c;
        c = binom(50,8);
        printf("c ist %d",c);
        return 0;
    }
    

    ....

    #include <stdio.h>
    #include <stdlib.h>
    
    int binom (int a, int b){
        int i;
        int bin = 1;
        for(i=1; i<b+1; i++){
            bin = bin *(a-(i-1))/i;
            printf("bin ist %d\n",bin);
        }
        return bin;
    }
    
    int main()
    {
        int c;
        c = binom(50,8);
        printf("c ist %d",c);
        return 0;
    }
    

    Rauskommt
    bin ist 50
    bin ist 1225
    bin ist 19600
    bin ist 230300
    bin ist 2118760
    bin ist 15890700
    bin ist 99884400
    bin ist 7738
    c ist 7738
    Process returned 0 (0x0) execution time : 0.177 s
    Press any key to continue.


  • Mod

    essio schrieb:

    SeppJ schrieb:

    essios Analyse würde ich mich übrigens nur halb anschließen. Offensichtlich ist bin irgendwo nicht richtig definiert, aber die richtige Lösung ist sicher nicht, es einfach global zu definieren.

    Damit war eig. die Deklaration gemeint und nicht die Definition. Die Definition muss man dann separat machen wie in der Funktion, sieht nämlich so aus als würde die main einen bin Wert bekommen der nur in der Funktion Deklariert ist.

    Und wo ist deiner Meinung nach der Unterschied zwischen einer global deklarierten Variablen und einer global definierten Variablen?

    Wenn sich durch double oder long int nichts ändert liegt es nicht an int.

    Er hat long und float geschrieben, nicht double. Und deine Schlussfolgerung ist falsch. long ist nicht garantiert größer als int. float ist in aller Regel sogar weniger genau als int. Dass deine Schlussfolgerung falsch ist, kannst du ganz leicht ausprobieren, indem du long long benutzt. Dann funktioniert der Code nämlich. long long ist nämlich garantiert 64 Bit lang, long nur mindestens 32. Was aber auch eine typische Größe für int ist. Das heißt, auf vielen Systemen sind int und long gleich genau.



  • SeppJ schrieb:

    essio schrieb:

    SeppJ schrieb:

    essios Analyse würde ich mich übrigens nur halb anschließen. Offensichtlich ist bin irgendwo nicht richtig definiert, aber die richtige Lösung ist sicher nicht, es einfach global zu definieren.

    Damit war eig. die Deklaration gemeint und nicht die Definition. Die Definition muss man dann separat machen wie in der Funktion, sieht nämlich so aus als würde die main einen bin Wert bekommen der nur in der Funktion Deklariert ist.

    Und wo ist deiner Meinung nach der Unterschied zwischen einer global deklarierten Variablen und einer global definierten Variablen?

    War die Deklaration nicht das erstellen eines Speichers für die Variable und Definition die Wertzuweisung?

    Deklaration:

    int bin;

    Definition:

    bin = 1;

    Wenn ich mich irre bedanke ich mich für die Korrektur. Bin selber schließlich nur ein Anfänger 🙂

    Er hat long und float geschrieben, nicht double. Und deine Schlussfolgerung ist falsch. long ist nicht garantiert größer als int. float ist in aller Regel sogar weniger genau als int. Dass deine Schlussfolgerung falsch ist, kannst du ganz leicht ausprobieren, indem du long long benutzt. Dann funktioniert der Code nämlich. long long ist nämlich garantiert 64 Bit lang, long nur mindestens 32. Was aber auch eine typische Größe für int ist. Das heißt, auf vielen Systemen sind int und long gleich genau.

    Du hast recht, verzeihung mein Fehler.

    Ich habe das Ergäbis, nach der double einsetzung, falsch intepretiert.

    long long kannte ich bisher noch nicht. Danke


Anmelden zum Antworten