Werteintragung im Array



  • Ich machs kurz:

    int main(int argc, char *argv[])
    {
    	int x, Counter;
    	float I1=0, I2=2, Unterteilungsstellen=I1, Streifenbreite=0.2222, Wertetabelle[11];
    
    	for(x=0, Counter=0; Unterteilungsstellen<=I2; Counter++, x++, Unterteilungsstellen+=Streifenbreite)
    	{
    		printf(" Counter: %d\n x=%d\n", Counter, x);
    		printf(" Werteintrag: %.2f\n\n\n", Unterteilungsstellen);
    		Wertetabelle[x]=Unterteilungsstellen;
    	}
    
    	Counter--;
    	printf(" Letzter Werteintrag: %.2f", Wertetabelle[Counter]);
    	return 0;
    }
    

    Worum geht es?
    Um den in Zeile 4 geschriebenen Wert 0.2222. Für diesen Wert funktioniert alles ganz toll. Verändert man nun den Wert in 0.2, überspringt er den letzten Werteintrag bei [10]. Ich verzweifle und blick einfach nicht warum, denn die Bedingungen in der for()-Schleife sind doch gar nicht erfüllt? 😕 😕 😕 😕



  • Das ist die perfekte Gelegenheit für den Debugger.



  • Unterteilungsstellen<=I2
    Mit float lassen sich nicht alle Zahlen genau darstellen, es kann also sein dass 10*0.2 nicht 2 entspricht. Versuchs mal mit double oder ändere die Bedingung.



  • dass 10*0.2 nicht 2 entspricht.
    sondern etwas kleiner oder größer (Problem) ist.



  • Das ist die perfekte Gelegenheit für den Debugger.

    Nur dass der leider nix ausspuckt. 😃 😃



  • sondern etwas kleiner oder größer (Problem) ist.

    Woran liegt das denn? An der Binärschreibweise..? Wie wird denn 0.2 dargestellt?



  • Gleitkommazahlen sind ein kompliziertes Dings, frag mal Wikipedia oder eine Suchmaschine.



  • TocToc schrieb:

    Das ist die perfekte Gelegenheit für den Debugger.

    Nur dass der leider nix ausspuckt. 😃 😃

    Du musst ihn natürlich auch noch benutzen. Setzt einen Breakpoint in Zeile 8 und kontrolliere, ob alle Variablen den gewünschten Wert haben.


  • Mod

    TocToc schrieb:

    sondern etwas kleiner oder größer (Problem) ist.

    Woran liegt das denn? An der Binärschreibweise..? Wie wird denn 0.2 dargestellt?

    So wie im Zehnersystem alles als Summen von Vielfachen von Zehnerpotenzen dargestellt wird (so wie zum Beispiel

    25.14 = 2*10^1 + 5*10^0 + 1*10^-1 + 4*10^-2
    

    ist), so wird dein Computer fast unter Garantie mit einem Binärsystem arbeiten. Versuch mal, wie du die Zahl 0.2 im Binärsystem darstellen kannst! Ich mach dir mal den Anfang, da ich die Vermutung habe, dass du das nicht alleine hin bekommst:

    • 2^0 = 1. Wie viele 1 sind in 0.2? 0. Also bisheriges Ergebnis (in Binärschreibweise) 0. Rest 0.2-0*1 = 0.2
    • 2^-1 = 0.5. Wie viele 0.5 sind in 0.2? 0. Also bisheriges Ergebnis (in Binärschreibweise) 0.0. Rest 0.2-0*0.5 = 0.2
    • 2^-2 = 0.25. Wie viele 0.25 sind in 0.2? 0. Also bisheriges Ergebnis (in Binärschreibweise) 0.00. Rest 0.2-0*0.25 = 0.2
    • 2^-3 = 0.125. Wie viele 0.125 sind in 0.2? 1. Also bisheriges Ergebnis (in Binärschreibweise) 0.001. Rest 0.2-1*0.125 = 0.075
    • 2^-4 = 0.0625. Wie viele 0.0625 sind in 0.075? 1. Also bisheriges Ergebnis (in Binärschreibweise) 0.0011. Rest 0.075-1*0.0625=0.0125.

    Führ das mal fort, bis du den Rest 0 hast, dann weißt du, was 0.2 im Binärsystem ist.

    (Falls du dich wunderst, wieso eine Zweierpotenz immer nur genau 0 oder 1 Mal in den vorherigen Rest passt: Das liegt natürlich da dran, dass es das Binärsystem ist, da kommen konstruktionsgemäß nur die Ziffern 0 und 1 vor.)



  • @SeppJ
    Als int. Aber als float?


  • Mod

    0.222222222222 schrieb:

    @SeppJ
    Als int. Aber als float?

    Deine ints haben aber viele Nachkommastellen.

    Als float geht das genau so. float heißt nur, dass dann beispielsweise statt 0.000010101 stattdessen 1.0101*2^-5 gespeichert wird (also getrennt 1.0101 und -5) oder statt 1010000 wird 1.01*2^6 gespeichert (also 1.01 und 6). Das ist es, was Fließkommazahl heißt, weil das Komma immer zu der ersten zählenden Stelle verschoben wird. Der große Vorteil davon ist, dass man mit dem gleichen Datentyp zugleich sehr, sehr kleine Zahlen mit hoher Genauigkeit darstellen kann (beispielsweise 0.00000000000000000000000000000010111 als 1.0111*2^-31 (ich hoffe, ich habe die Nullen korrekt gezählt)) und zugleich sehr, sehr große Zahlen mit ausreichender Genauigkeit (also beispielsweise 10111000000000000000000000000000000 als 1.0111*2^34) darstellen kann.

    Das "getrennt" Speichern der Zahl und des Exponenten ist dabei natürlich nicht all zu wörtlich zu nehmen. Das ist schon alles irgendwie zusammen in den 4 bzw. 8 Bytes des floats/doubles codiert. Und zwar nicht unbedingt in der Form, wie man einen normalen Integer speichern würde. Ich erkläre in diesem Beitrag die Mathematik auf Binärsystemebene, nicht die Strom-an-Strom-aus-Muster in der Maschine.

    Wenn man es technisch ganz genau nimmt, wird bei den gängigen Systemen die führende 1 auch nicht mit abgespeichert. Denn da bei der Erklärung, die ich oben gegeben habe, ist die erste Stelle per Konstruktion immer eine 1. Daher kann man sich auch sparen, sich diese explizit zu merken und hat somit effektiv 1 Bit mehr zur Verfügung.

    Wenn man es noch genauer nimmt, fällt auf, dass ich im vorherigen Absatz gelogen habe, denn wenn man 0 speichern will, dann ist die erste Ziffer keine 1. Es gibt daher ein paar Sonderwerte, die anders gespeichert werden. Das erkläre ich hier aber nicht noch genauer, denn: Es ist inzwischen das Informationszeitalter. Solche Dinge stehen im Lexikon erklärt; Lexika sind frei für jedermann zugänglich.



  • So genau wollte ich es ja gar nicht wissen.... Wenigstens ist das Problem vom TO klar.



  • Vielen Dank @SeppJ, jetzt hab ich's. Sprich double ist dann genauer, weil eben mehr dieser Nachkommastellen generiert werden können, weil das Ergebnis eine Annäherung an 0.2 ist.

    PS: Dem Binärsystem bin ich einigermaßen geläufig 😉



  • Muss das Ganze gerade nochmal aufrollen:
    Trägt man für I1=1 und I2=3 oder eben ganzzahlige natürliche Zahlen ein, ist das gleiche Problem wieder da: Ab dem Wert 0.2 wird der letzte Array-Eintrag übersprungen. Why denn nun schon wieder...? 😕


  • Mod

    Vermutlich immer noch aus dem gleichen Grund. Code?



  • TocToc schrieb:

    Vielen Dank @SeppJ, jetzt hab ich's. Sprich double ist dann genauer, weil eben mehr dieser Nachkommastellen generiert werden können, weil das Ergebnis eine Annäherung an 0.2 ist.

    PS: Dem Binärsystem bin ich einigermaßen geläufig 😉

    Leider ist 0.2 dem Binärsystem nicht so geläufig.
    0.25 wäre toll.



  • Außerdem niemals schleifen auf float, außer man weiß auswendig, daß der double nur für Vielfache von Zweierpotenzen genau ist und solange Abstände nicht mehr als ca 53 Bit kleiner als die Beträge sind und wenn als Benutzereingabe schon gar nicht.

    for(int i=...)
    	{
    		double x=(I2-I1)/streifenanzahl*i+I1;//rundet jedesmal aufs neue und immer frisch und gut, 
    //mal hoch mal runter, hab keine Sorgen, Herr Intel macht das schon für mich. 
    		double y=x*x-1;
    		//rechnen mit x|y
    	}
    }
    

    Am (hier unsichtbaren, deswegen ja so gemeinen) "int" in int I1,I2 mit nachfolgender Integer-Division haben zwei Kommilitonen, die eigentlich ganz zucker programmierten, mal zusammen einen ganzen Tag gesucht. ⚠



  • Das habe ich jetzt ehrlich gesagt net wirklich verstanden und weiß auch nicht was die Rechningen im Code bewirken sollen...


  • Mod

    Wenn du Antworten auf deine Beiträge möchtest, dann solltest du Fragen stellen. Es wird gewiss niemand ein Ratespielchen mit dir machen, was du aus welchem Beitrag in welchem Maße nicht verstanden hast.



  • Na, die Rechnungen die er vorgeführt hat und die Aussage mit dem "verstecktem int", was das überhaupt bedeuten soll.


Log in to reply