Rechnen mit Zahlen


  • Mod

    Ich glaube du hast es immer noch nicht verstanden. Spiel mal hiermit herum:

    int a = 11;
    int b = 22;
    int c = 44;
    
    printf("BlaBla %d Dudeldu %d lalala %d ping %d pong %d tischtennis %d \n", a, b, c, 55, 88-11, a+b);
    printf("BlaBla %d Dudeldu %d lalala %d ping %d pong %d tischtennis %d \n", 99-11, a, 55, c, b, b);
    // Und andere Kombinationen
    
    // oder auch
    printf("%d + %d = %d \n", a, b, a-b); 
    printf("%d = %d * %d \n", a*b, b, a);
    


  • hm okay...also mit %d sagen wir ja, dass wir eine dezimale Zahl ausgeben möchte. Und mit den Parametern bestimmen wir welche das ist? Und dann können wir sie noch mit anderen Parametern + oder * nehmen lassen? Stimmt´s?



  • Windassel schrieb:

    hm okay...also mit %d sagen wir ja, dass wir eine dezimale Zahl ausgeben möchte. Und mit den Parametern bestimmen wir welche das ist?

    Ja.

    Windassel schrieb:

    Und dann können wir sie noch mit anderen Parametern + oder * nehmen lassen? Stimmt´s?

    Operatoren gehören nicht zu den Parametern. Die sind wie Funktionen mit eigenen Parametern. Die werden als erstes ausgerechnet, und dann wird das Ergebnis zurückgegeben bzw. die Funktion printf wird erst mit dem fertig berechneten Ergebnis aufgerufen.

    int add(int a, int b)
    {
      return a + b;
    }
    
    int main()
    {
      printf("%d + %d = %d\n", 1, 1, 3);
      printf("%d * %d = %d\n", 3, 3, add(3, 3));
    }
    


  • // kap003/listing009.c
    #include <stdio.h>
    
    int main(void) {
        int a = 11;
        int b = 22;
        int c = 44;
        int d = 54;
        int e = 70;
        int f = 89;
    
        printf(" %d\n  %d\n  %d\n  %d\n  %d\n  %d \n", a + (c * b), b, d, c, e, f - 90);
        system("PAUSE");
        return 0;
    }
    

    Also, theoretisch könnten wir das mit den Parametern so stehen lassen, ist aber ein schlechter Stil? Eher sollten wir das dann so schreiben?:

    [cpp]// kap003/listing009.c
    #include <stdio.h>

    int main(void) {
    int a = 11;
    int a1 = a + (c * b);
    int b = 22;
    int c = 44;
    int d = 4;
    int e = 54;
    int f = 90;
    int g = 13;

    printf(" %d\n %d\n %d\n %d\n %d\n %d \n", a1, b, d, c, e, f - g);
    system("PAUSE");
    return 0;
    }[/cpp]

    Richtig?



  • Windassel schrieb:

    ist aber ein schlechter Stil? Eher sollten wir das dann so schreiben?:

    Nö ich habe das nur zur Erklärung geschrieben.

    printf("%d\n", 5 + 3);
                  |-----|
                   Das ist im Endeffekt nur als 1 Parameter anzusehen, 
                   weshalb man keine "Parameter addiert". Die Addition
                   findet bereits statt, bevor der Parameter (der hier einfach
                   nur 8 wäre) übergeben wird.
    


  • haha okay, dann hab ich das jetzt verstanden 🙂



  • Windassel schrieb:

    http://www.amazon.de/Grundkurs-C-Programmierung-verständlich-erklärt-Computing/dp/3836215462/ref=sr_1_2?ie=UTF8&qid=1308391485&sr=8-2

    Das ist das Buch, was ich mir bestellt habe. 🙂

    Das dürfte ein ziemlicher Klogriff gewesen sein - der Autor des Buches ist hier schon berüchtigt.

    Was die Stilfrage angeht, das ist ein Stück weit Geschmackssache und vom umgebenden Code abhängig. Wichtig ist, dass der Code übersichtlich bleibt; wie man das erreicht, ist im Einzelfall zu entscheiden. Es kann dabei hilfreich sein, einen Ausdruck über mehrere Zeilen zu verteilen. Beispiel:

    printf("%f\n%f\n", (double) (bench[1] - bench[0]) / CLOCKS_PER_SEC,
                         (double) (bench[2] - bench[1]) / CLOCKS_PER_SEC);
    

    Das ist aus einem einfachen Benchmark-Programm entnommen, wo bench die bis zu bestimmten Zeitpunkten verbrauchte CPU-Zeit enthält. Worauf ich hinaus will ist, dass das in der Form deutlich lesbarer ist, als wenn man es in eine Zeile hintereinander schreibt:

    printf("%f\n%f\n", (double) (bench[1] - bench[0]) / CLOCKS_PER_SEC, (double) (bench[2] - bench[1]) / CLOCKS_PER_SEC);
    

    ...was es für mein Verständnis zu besserem Stil macht.

    In deinem konkreten Beispiel kann ich keinen Vorteil darin erkennen, alle Werte in Variablen zu stopfen; das liegt aber größtenteils daran, dass sowohl die Werte als auch die Namen willkürlich gewählt sind. Ob du jetzt a1 oder a * (b + c) schreibst, ist ziemlich gleichgültig, wenn weder a1 noch a * (b + c) den Sinn des Unterfangens verdeutlichen. Etwas realistischer gewählt womöglich:

    /* quadrat.c */
    
    #include <stdio.h>
    
    int main(void) {
      int seitenlaenge = 10;
      int flaeche = seitenlaenge * seitenlaenge;
    
      printf("Ein Quadrat mit Seiten der Länge %d hat eine Fläche von %d\n", seitenlaenge, flaeche);
    
      return 0;
    }
    

    ...worin sinnvolle Variablennamen dabei Helfen, den Sinn des Codes zu verdeutlichen. Es mag dann womöglich kürzere, allgemein übliche Notationen geben - das ist in der Mathematik häufiger der Fall. Beispielsweise wäre Folgendes völlig vertretbar:

    /* rechtwinkliges Dreieck  */
    
    #include <math.h>
    #include <stdio.h>
    
    int main(void) {
      double a = 3.0;                 /* Ankathete    */
      double b = 4.0;                 /* Gegenkathete */
      double c = sqrt(a * a + b * b); /* Hypothenuse  */
    
      printf("%f^2 + %f^2 = %f^2\n", a, b, c);
    
      return 0;
    }
    

    ...und wenn da keine gute Methode findet, kann (und sollte!) man einen Kommentar daneben schreiben, der erklärt, was man mit der ganzen Schose meint.



  • seldon schrieb:

    Windassel schrieb:

    http://www.amazon.de/Grundkurs-C-Programmierung-verständlich-erklärt-Computing/dp/3836215462/ref=sr_1_2?ie=UTF8&qid=1308391485&sr=8-2

    Das ist das Buch, was ich mir bestellt habe. 🙂

    Das dürfte ein ziemlicher Klogriff gewesen sein - der Autor des Buches ist hier schon berüchtigt.

    Toll, warum das denn? :(:(:(:/:/:/



  • In dem Buch stehen auch wirklich manchmal Sachen drinne, wo ich garnet weiß, wo er die her hat Oo





  • Und was soll ich jetzt machen? Soll ich jetzt noch die restlichen 300 Seiten durcharbeiten? Denn gleich beim nächsten Beispiel geht´s schon wieder mit Fragen los, die mir das Buch nicht beantworten kann.



  • Naja, wenn du mit diesem Buch weitermachst, musst du dich darauf einstellen, am Ende einige Dinge wieder verlernen zu müssen. Insbesondere in Bezug auf undefiniertes Verhalten ist Jürgen Wolf höchst unzuverlässig - er gehört der Denkschule des "funktioniert bei mir, wird schon richtig sein" an, und das ist für C eine ganz schlechte Einstellung.

    Beispiel: Er behauptet in dem Buch, das du gerade benutzt, dass bei Funktionsaufrufen die Parameter von rechts nach links ausgewertet werden. In Wahrheit ist die Reihenfolge undefiniert (d.h. ein Compiler kann es machen, wie er gerade lustig ist), was, wenn man mal einen anderen Compiler als Herr Wolf benutzen will/muss, zu ausgesprochen unangenehmen Debugging-Sessions führen wird.

    Gerade für Anfänger ist das insofern besonders problematisch, als dass man als Anfänger keinerlei Möglichkeit hat, diese Fehler zu bemerken.

    Ich kann dir nur raten, dir ein besseres Buch zuzulegen. Wie gut sind deine Englisch-Kenntnisse?



  • CStoll schrieb:

    Naja, ganze Zahlen sind nicht genau genug für derartige Berechnungen.

    Einspruch: die Genauigkeit von Z ist absolut, sie sind niemals ungenau (hat nix mit meinem Namen zu tun 😃 ) allerdings sind die Ganzen Zahlen für solche Berechnungen eher ungeeignet; hier ist der Bereich der Reellen Zahlen zielführender, deren Darstellung in Computern übrigens fast immer ungenau ist.

    Btw, lasst euch durch meine philosophische Betrachtungsweise nicht verwirren.
    Weitermachen! 🙂



  • "Die Genauigkeit der Zahlen im Verhältnis zu der benötigten Speichermenge.." 🙄



  • cooky451 schrieb:

    "Die Genauigkeit der Zahlen im Verhältnis zu der benötigten Speichermenge.." 🙄

    Ich teste mal...
    (gcc mingw 4.5.0 auf auf sempron@1800MHz mit -march=native -O3)

    unsigned short c=0;
        for(int d=1;;++d){
            if(!++c) std::cout<<d<<'\r'<<std::flush;
            if((d+1)-1!=d){
                std::cout<<"Fehler bei "<<d<<'\n';
                return 1;
            }
        }
    

    Das Programm läuft alle paar Sekündchen seine 4.2Mrd Zahlen durch und findet einfach keinen Fehler.

    Für float ist das schon viel einfacher.

    float d=sqrt(2);
        if((d+1)-1!=d)
        {
            std::cout<<"Fehler bei "<<d<<'\n';
            return 1;
        }
    

    Fehler.



  • cooky451 schrieb:

    "Die Genauigkeit der Zahlen im Verhältnis zu der benötigten Speichermenge.." 🙄

    Yep, besonders fies, wenn eine Reelle Zahl kein Bruch zweier Ganzer Zahlen ist. Beispiel: sqrt(2). Hier offenbart sich die ganze Unzulänglichkeit der Digitaltechnik. 😃



  • Z schrieb:

    cooky451 schrieb:

    "Die Genauigkeit der Zahlen im Verhältnis zu der benötigten Speichermenge.." 🙄

    Yep, besonders fies, wenn eine Reelle Zahl kein Bruch zweier Ganzer Zahlen ist. Beispiel: sqrt(2). Hier offenbart sich die ganze Unzulänglichkeit der Digitaltechnik. 😃

    Ach, sqrt(2) war willkürlich. Die

    float d=0.1;
        if((d+1)-1!=d)
    

    wirkt genauso.

    Das hier find ich auch immer wieder schön:

    for(double d=0;d<1;d+=0.1)
            std::cout<<d<<' ';
        std::cout<<'\n';
        for(double d=0;d<1;d+=0.05)
            std::cout<<d<<' ';
        std::cout<<'\n';
    

    mit

    0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
    0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95
    

    Die zweite 1 macht Urlaub.



  • volkard schrieb:

    Z schrieb:

    cooky451 schrieb:

    "Die Genauigkeit der Zahlen im Verhältnis zu der benötigten Speichermenge.." 🙄

    Yep, besonders fies, wenn eine Reelle Zahl kein Bruch zweier Ganzer Zahlen ist. Beispiel: sqrt(2). Hier offenbart sich die ganze Unzulänglichkeit der Digitaltechnik. 😃

    Ach, sqrt(2) war willkürlich. Die

    float d=0.1;
        if((d+1)-1!=d)
    

    wirkt genauso.

    Naja, hier spielt dir die Implementation der Fließkommazahlen zur Basis 2 einen Streich. Würden floats auf Zehnerpotenzen beruhen, würde es klappen. Mit sqrt(2) gehts halt immer schief, außer du nimmst sqrt(2) selbst als Basis deiner Fließkommazahlen. 😉


  • Mod

    Z schrieb:

    Naja, hier spielt dir die Implementation der Fließkommazahlen zur Basis 2 einen Streich.

    Dann nimmste eben 1/3 und hast das gleiche Problem wieder.



  • jetzt wollte ich zum Thema eigentlich meinen Ärger über das redundante printf auslassen (3fach hält wohl besser: int x printf %d ,x; es ginge doch auch int & print x,y,z (in dieser Reihenfolge und dann am Ende einfach OUT)

    I x,y
    IP z
    OUT-TV CR LF
    

    , aber neee..., ziemlich krank..

    ...und ihr seit jetzt aber schon wieder bei einem ganz anderen Thema - fällt mir dazu nicht auch nicht noch was ein? hm...naja, die Fpus könnten Festkommarechnungsüberprüfung anbieten, gänzlich per Interrupt (oder so, der mit vielen Registern kombiniert ganz schön große und performante Registerkombifestkommarechnung betreibt, so daß man auf Spracherweiterungen wie C-XSC verzichten könnte. Oder man läßt das ganze gleich von der Grafikkarte in verschiedenen Zahlensystemen inkl. Proberechnungen ausrechnen...;)


Anmelden zum Antworten