Zahlenfolgen



  • Hi, ich habe hier ein kleine Problem und komm einfach nicht auf die Lösung.

    Es soll eine Zahlenfolgen eingegeben werden, nullterminiert. Daraus soll der Mittelwert errechnet werden und der größte Abweichung zu diesem ausgegeben werden.
    Mittelwert funktioniert, aber bei der Abweichung kommt nur Mist raus.

    #include <stdio.h>
    
    int readInt()
    {
    	int number;
    	scanf("%d", &number);
    	return number;
    }
    
    int abs( int number )
    {
     int betrag;
    
     if ( number < 0 )
        {
            betrag = -number;
        }
     else
        {
            betrag = number;
        }
    return betrag;
    }
    
    int zahlenfolge()
    {
        int mittelwert = 0, summe = 0, count = 0;
    	int number;
    	int abstand, altabstand = 0, abweich;
    
    	printf("Zahlenfolge:");
    
    	number = readInt();
    	while (number != 0)
    	{
    		//Mittelwert
    
    		summe += number;
    
    		count++;
    
            mittelwert = summe / count;
    
            //Abweichung
    
            abstand = number - mittelwert;
    
            if ( abstand >= altabstand)
                {
                    abweich = abstand;
                }
            altabstand = abstand;
    
            number = readInt();
    	}
    
    	if (count == 0)
            {
                printf("Folge ist 0");
            }
        else
            {
                printf("Mittelwert der Folge: %d \n", mittelwert);
                printf("Groesste Abweichung vom Mittelwert der Folge: %d \n", abweich);
            }
    return count;
    }
    
    int main()
    {
        zahlenfolge();
        return 0;
    }
    

    Eventuell kann mir jemand weiterhelfen.


  • Mod

    if ( abstand >= altabstand)
            {
              abweich = abstand;
            }
    

    Warum vergleichst du hier mit dem Abstand aus dem vorherigen Durchgang? Du willst doch wissen, ob der neue Abstand größer ist als der bisher größte Abstand, nicht der Abstand aus der vorherigen Rechnung. Du musst also mit abweich vergleichen. Den Abstand des vorherigen Durchgangs benötigst du hingegen überhaupt gar nicht.

    Außerdem willst du wohl den Betrag der Abweichung, nicht die absolute Abweichung. Du hast ja schon eine Betragsfunktion geschrieben, du nutzt sie nur nirgendwo. (Die Betragsfunktion gibt es übrigens auch schon fertig in der Standardbibliothek. Sie wird im Header stdlib.h deklariert. Rate mal, wie sie heißt 🙂 )

    Jedoch ergibt sich ein ganz anderes Problem: Du kennst während der Rechnung doch noch gar nicht den Mittelwert. Du kennst nur die bis dahin beste Schätzung. Diese ist es, mit der du hier vergleichst. Aber was ist, wenn sich der Mittelwert später noch krass ändert? Nehmen wir mal an, wir hätten die beiden kleinen Fehler von oben korrigiert (solltest du alleine hin bekommen, oder?) und geben folgendes ein: "1 100 1 0"

    • Im ersten Durchlauf ist die Summe 1, der Mittelwert 1 und der Abstand davon logischerweise 0. Der bisher größte Abstand ist also 0.
    • Im zweiten Durchlauf ist die Summe 101, der Mittelwert 50* und der momentane Abstand ist abs(100-50)=50. Der bisher größte Abstand ist also 50.
    • Im dritten Durchlauf ist die Summe 103, der Mittelwert 34 und der momentane Abstand ist (1-34)=33. Das ist weniger als 50. Der bisher größte Abstand ist also immer noch 50.

    Wir haben also am Ende einen Mittelwert von 34, aber der größte gemessene Abstand ist nicht etwa 66, sondern 50!
    Dieses Problem ist nicht ganz einfach zu lösen. Ich vermute sogar, es ist Kern der Aufgabe, dies zu lösen. Habt ihr denn nichts zu diesem Thema besprochen? Der naive Ansatz wäre hier, dass man alle Zahlen irgendwo speichern muss und hinterher noch einmal alle Werte durchgeht und mit dem Mittelwert vergleicht. Da du aber nicht weißt, wie viele Zahlen kommen, muss der Speicher dafür dynamisch besorgt werden. Ein komplexes Thema in C, das ich nicht mal eben so erklären kann. Daher vermute ich, dass es in deinem Kurs dran gekommen sein muss.

    Es mag auch sein, dass es eine clevere Lösung gibt, um die Aufgabe mit einem einzigen Durchgang zu lösen. Ich weiß, dass man zumindest die mittlere Abweichung vom Mittelwert in einem Rutsch ausrechnen kann, daher will ich nicht ausschließen, dass es nicht auch für die größte Abweichung geht. Vielleicht wenn man sich das Paar aus größtem bisher gemessener Abweichung und den dazugehörigen Messwert merkt? Klingt erfolgsversprechend, müsste ich aber genauer durchdenken, was man genau machen muss und ob das in wirklich jedem Sonderfall klappt (bzw. du solltest das machen, denn es ist deine Aufgabe). Falls dein Kurs eher um clevere Algorithmen als um technische Aspekte der Programmierung geht, ist vermutlich dies der erwartete Lösungsweg. Du musst wissen, was wohl eher verlangt wird.

    *: Dass Integermathematik anders ist, als der Laie es erwartet, ist dir klar, oder? So ist beispielsweise 5/2 nicht etwa 2.5, sondern 2. Entsprechend ist 101/2 == 50 und 102/3 == 34. Wie beim Teilen in der Grundschule: Einfach den Rest weglassen 🙂



  • ~(Für SeppJ leg ich schnell ein weiches Kissen auf den Tisch.)~

    In einem Rutsch gehste durch und sammelst dabei Anzahl, Summe, Minimum und Maximum.

    Danach erst machst Du den Mittelwert und schaust, ob Minimum oder Maximum von diesem am weitesten weg sind.


  • Mod

    volkard schrieb:

    ~(Für SeppJ leg ich schnell ein weiches Kissen auf den Tisch.)~

    Danke, das war echt nötig. Ich war zu versteift darauf, endlich mal mein geheimes Numerikerwissen über die mitlaufende Berechnung der Varianz leicht verändert einzusetzen, dass mir die offensichtlichste und einfachste Lösung gar nicht in den Sinn kam. Das ist dann wohl auch des Rätsels Lösung, was der Aufgabensteller verlangt. Denn das ist weder ein ausgefuchster Algorithmus, noch benötigt man fortgeschrittene Sprachmittel. Und man lernt in einem Durchgang die drei oft benötigten Vorgehensweisen zur Berechnung von Minimum, Maximum und Mittelwert einer Zahlenfolge. Gute Aufgabenstellung 👍



  • und das ist nur der erste Teil der aufgabe. da wirds dann noch ganz verrückt. aber ich probier das jetzt mal mit dem min und max. mal sehen obs klappt. danke auf jedenfall erstmal 🙂



  • Ich habs fertig. Es funktioniert auch soweit ich das sehen kann.

    Im zweiten Teil der Aufgabe sollte dann noch die maximal Ziffernzahl der größten Zahl ermittelt und daraus ein Sternmuster gezeichnet werden. Also Sternchen, dann Anzahl der Ziffern als Leerzeichen und wieder ein Sternchen. Das ganze auf maximal 50 Zeichen breit und 25 hoch.

    #include <stdio.h>
    
    int readInt()
    {
    	int number;
    	scanf("%d", &number);
    	return number;
    }
    
    int abs( int number )
    {
     int betrag;
    
     if ( number < 0 )
        {
            betrag = -number;
        }
     else
        {
            betrag = number;
        }
    return betrag;
    }
    
    int zahlenfolge()
    {
        int summe = 0, count = 0;
    	int number, min, max;
    	int mittelwert, abweich, minabweich, maxabweich;
    	int ziffern = 1, biggest;
    	int height, stars, oldziff;
    
    	printf("Zahlenfolge eingeben (nullterminiert):");
    
    	number = readInt();
        max = number;
    	while (number != 0)
    	{
    
            summe += number; //Summe
    		count++; //Anzahl
            if (count == 1)
            {
                min = number;
            }
    		if (number >= max)
            {
                max = number; //Maximum
            }
    
            if (number <= min)
            {
                min = number;  //Minimum
            }
            number = readInt();
            }
    
            mittelwert = summe / count; //Mittelwert
    
    //Abweichung (kürzer?)
    
            if ( min < 0 && mittelwert < 0)
            {
                minabweich = abs(min) - abs(mittelwert);
            }
            if ( min < 0 && mittelwert > 0)
            {
                minabweich = abs(min) + mittelwert;
            }
            if ( min > 0 && mittelwert > 0)
            {
                minabweich = mittelwert - min;
            }
    
            if ( max < 0 && mittelwert < 0)
            {
                maxabweich = abs(mittelwert) - abs(max) ;
            }
            if ( max > 0 && mittelwert > 0)
            {
                maxabweich = max - mittelwert;
            }
            if ( max > 0 && mittelwert < 0)
            {
                maxabweich = abs(mittelwert) + max;
            }
    
            if (minabweich >= maxabweich)
            {
                abweich = minabweich;
            }
            else
            {
                abweich = maxabweich;
            }
    
    // Max Ziffernzahl
    
            if ( abs(min) > abs(max))
            {
                biggest = abs(min);
            }
            else
            {
                biggest = abs(max);
            }
    
            while (biggest / 10 > 0)
            {
                ziffern++;
                biggest = biggest / 10;
            }
    
    //Ausgabe
    
                    if (count == 0)
                    {
                        printf("Folge ist 0");
                    }
                    else
                    {
                        printf("Mittelwert der Folge: %d \n", mittelwert);
                        printf("Groesste Abweichung zum Mittelwert: %d \n", abweich);
                        printf("Maximale Ziffernzahl: %d \n", ziffern);
                    }
    
    //Sterne
    
            stars = (50 / (ziffern + 1));
            height = (25 / (ziffern + 1));
            while (height > 0)
            {
                while (stars > 0)
                {
                    printf("*");
                    stars--;
                    oldziff = ziffern;
                        while (ziffern > 0)
                        {
                            printf(" ");
                            ziffern--;
                        }
                    ziffern = oldziff;
                }
                while (ziffern >= 0)
                {
                    printf("\n");
                    ziffern--;
                }
                stars = (50 / (oldziff + 1));
                ziffern = oldziff;
                height--;
            }
    
    return 0;
    
    }
    
    int main()
    {
        zahlenfolge();
        return 0;
    }
    


  • #include <stdio.h>
    
    int readInt() {//gute Funktion
    	int number;
    	scanf("%d", &number);
    	return number;
    }
    
    int abs(int number) {//gekürzt
    	if(number >= 0) {
    		return number;
    	}
    	else {
    		return -number;
    	}
    }
    
    int zahlenfolge() {
    	printf("Zahlenfolge eingeben (nullterminiert):");
    
    	number = readInt();
    	max = number;
    	min = number;//kein if(count == 1) min=number;!
    		//seltsam, daß Du für den genau gleichen Zweck zwie so 
    		//Unterschiedliche Wege nahmst. 
    	while(number != 0) {
    		summe += number;
    		count++;
    		if(number > max) {//> statt >=
    			max = number;
    		}
    		if(number < min) {
    			min = number;
    		}
    		number = readInt();
    	}
    
    	mittelwert = summe / count; //Mittelwert
    
    //Abweichung (kürzer?)//Jup. Und richtiger. 
    
    	minabweich = abs(min-mittelwert);
    	maxabweich = abs(max-mittelwert);
    	abweich=max(minabweich,maxabweich);
    
    //den Rest verstehe ich nicht (hab gerade keinen Bock). 
    	return 0;
    
    }
    
    int main() {
    	zahlenfolge();
    	return 0;
    }
    


  • stimmt, so geht das mit der abweichung besser. ka warum ich nicht gleich draufgekommen bin..



  • Dann bleiben noch die Sterne. Die versteh ich nicht ganz.
    Vielleicht ist der Prof Fan davon Schleifen schlicht zu halten, indem man möglichst viel als Nachberechnung oder Vorberechnung macht und will das zeigen/abprüfen. In "Sterne" hast nur while-Schleife, statt for-Schleifen, das wundert mein Stilgefühl.



  • Dann bleiben noch die Sterne. Die versteh ich nicht ganz.
    Vielleicht ist der Prof Fan davon Schleifen schlicht zu halten, indem man möglichst viel als Nachberechnung oder Vorberechnung macht und will das zeigen/abprüfen. In "Sterne" hast nur while-Schleife, statt for-Schleifen, das wundert mein Stilgefühl.



  • wir dürfen zunächst nur while schleifen, if else anweisungen und den stdio header nutzen. Die Aufgabe mit den Sternen soll wohl da sein um geschachtelte Iterationen zu üben.



  • Ok, dann noch ein Mini-Einwurf:

    oldziff = ziffern;
                        while (ziffern > 0)
                        {
                            printf(" ");
                            ziffern--;
                        }
                    ziffern = oldziff;//weg wegen
    
    newzif = ziffern;
                        while (newzif > 0)
                        {
                            printf(" ");
                            newzif--;
                        }
    //weg halt. wollte eh "ziffern" nicht verändern.
    

Log in to reply