Zeichenkettenarithmetik


  • Mod

    softpad schrieb:

    Beeindruckend wie schnell ein 64 Bit Rechner die Schleifen hochzählt,
    Selbst wenn man die Zählköpfe der for Schleifen auf 5000 setzt und
    dem Rechner zwischen jedem Wort aufträgt einen Zahlenkörper von dieser
    Größe durchzukalkulieren ----ohne Ausgabe---- dauert es doch immer nur Sekundenbruchteile

    Das ist einfach totaler Unsinn, so eine Zeitschleife zu programmieren. Erstens zählt ein Computer sowieso ungeheuer schnell, wenn er sonst nichts tut; zweitens wird die Schleife wahrscheinlich sowieso vollständig wegoptimiert, da sie einfach nichts tut; drittens ist busy-waiting schlechter Stil; viertens passt das nicht mehr, wenn dein Rechner schneller oder langsamer wird. Wenn du zeitabhängiges Programmverhalten möchtest dann nimm auch Funktionen die von der Zeit abhängen.



  • Wenn du den Compiler optimieren lässt, merkt der sogar, dass da nichts passiert und optimiert das weg -> keine Pause.
    Darum ja das sleep.

    pause ist auch ein Befehl von Windows.
    Der wartet auf einen Tastendruck. Also auch etwas anderes als eine bestimmte Zeit warten.
    Mit getchar kannst du das auch erreichen.

    Es reicht auch, das fflush im if-Zweig zu machen (und nicht nach jedem Zeichen).

    Schau dir mal isspace aus ctype.h an.



  • Falls man mal echt aktiv warten will, bei mir hat sich immer

    for(...)
       cout<<"";//ups, ist ja C, denke printf("") geht auch.
    

    bewährt, da hat sich noch kein Optimierer rangetraut.

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Dann muss ich nachlegen mit Chaos-Berechnungen, wie

    global double x=LaufzeitzufallZwischen(-2,+2);
    

    und je

    for(int i=0;i<wartezeit;++i)
       x=x*x-2;//Ich liebe diese Folge! Sie bleibt brav zwischen -2 und +2 
       //eingesperrt. Sie ist fehlerverstärkend, chaotisch. Und doch soo einfach. 
       //Übrigens ein Beispiel für einen Zufallszahlengenerator, der 
       //zwar langfristig total nicht vorhersagbar ist, wie das Wetter in Tübingen, 
       //der aber kurzfristig so unirdisch schlecht ist, daß man weinen müßte. 
       //Schon im zweidimenionalen Phasenraum ist er nicht im Mindesten irgendwie 
       //gleichverteilt, sondern zeichnet eine scharfe Parabel mit nochtmal einem 
       //leisen Halo drumherum.
    

    Wobei ich dann x auf jeden Fall bei Programmende auf den Bildschirm bringen muss! Tue ich es nicht, kann der Compiler alle meine Zeitschleifen wegoptimieren.
    Es reicht ja,

    if(x==0.2)
       cout<<"(Diese Zeile bitte ignorieren, sie ist nur dazu da, den "
          "Compiler zu ver*****en.)\n";//kommt praktisch nie vor, vielleicht einmal 
          //in 2^40 Läufen oder so.
    


  • volkard schrieb:

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Aufrufe externer Bibliotheksfunktionen (bin jetzt zu faul den exakten Wortlaut nachzuschlagen, you get the idea...) gehören zum beobachtbaren Verhalten.

    Dann muss ich nachlegen mit Chaos-Berechnungen, wie

    global double x=LaufzeitzufallZwischen(-2,+2);
    

    Wenn da volatile statt global steht, gehört das auch zum beobachtbaren Verhalten. Insbesondere darf der Compiler nichtmal bei

    volatile int x;
    x = 0;
    x = 0;
    

    eine einzige Zuweisung wegschmeißen.

    (Nicht dass ich das je zum Warten benutzen würde.)


  • Mod

    Bashar schrieb:

    volkard schrieb:

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Aufrufe externer Bibliotheksfunktionen (bin jetzt zu faul den exakten Wortlaut nachzuschlagen, you get the idea...) gehören zum beobachtbaren Verhalten.

    Wenn die Implementierung aber beweisen kann, was diese Bibliotheksfunktion macht (weil sie die Standardbibliothek kennt und auch erkennt, dass du gegen diese linkst*), dann ist die Optimierung wieder erlaubt. Es wird nämlich nirgendwo explizit die von dir beschriebene Klausel verlangt, sondern sie ist lediglich indirekt eine Folge davon dass eine unbekannte, externe Funktion Nebeneffekte haben könnte.

    Das erlaubt überhaupt erst Optimierungen der Standardbibliotheksfunktionen, wie printf("%s\n", foo); zu puts(foo); und ähnliches, die durchaus durchgeführt werden. Oder sqrt(2) zu 1.41421356237 und viele andere mehr. Sehr wichtige Optimierungsmöglichkeit.

    *: Beim GCC läuft dieser "Beweis" des Linkens gegen die Standardbibliothek beispielsweise so, dass du nicht die built-in Funktionen abgeschaltet hast. Auf diese Weise kann schon der Compiler die Optimierung durchführen.



  • Das hier ist der Satz, allerdings aus dem C++-Standard, den ich anscheinend meinte.

    The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

    In C gibt es das, wie so oft, nicht so klar ausgedrückt.



  • Bashar schrieb:

    volkard schrieb:

    Und indem ich meinen Trick hier poste, riskiere ich, daß in der nächsten Compiler-Version jemand genau das wegoptimiert. 🤡

    Aufrufe externer Bibliotheksfunktionen (bin jetzt zu faul den exakten Wortlaut nachzuschlagen, you get the idea...) gehören zum beobachtbaren Verhalten.

    klar gottete ich die idea. Was extern ist, ist extern. Fertig.

    Aber std::-Sachen nenne ich nicht "externe Bibliotheksfunktionen"! War da nicht der MSVC6.1 so schlau, std::swap je nach Typ auf einen Dreieckstausch oder auf einen asm XCHG zu legen, während ein händisch geschriebenes swap mit genau dem selben Sourcecode IMMER zu einem Dreieckstausch wurde?

    Ich hoffe, der Standard verspricht, daß cout<<"" nix tut. Falls er es nicht verspricht, ist das doch eine Lücke.


  • Mod

    Bashar schrieb:

    The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

    In C gibt es das, wie so oft, nicht so klar ausgedrückt.

    Auch in C++ bedeutet das nicht, dass jeder istream::operator<< unoptimierbar ist. Der Call an die Library I/O Funktion ist der letztlich daraus resultierende OS-Call (z.B. read/write unter Linux). Davor darf da gerne optimiert werden wie der Compiler lustig ist.



  • Ok Ich hab's schon verstanden! werde natürlich in Zukunft die von
    dir vorgeschlagen Funktion sleep verwenden. sleep(1) hatte Ich auch ausprobiert.. es wartet allerdings eine Minute zwischen den Worten... das man
    so eine Schleife nicht beim echten Programmieren als Wartezeit benutzt ist mir
    klar! Ich werde mir die Arbeitsweise von sleep genauer anschauen... und es in dem Programm ersetzen ... Danke für eure Tips!


  • Mod

    softpad schrieb:

    Ok Ich hab's schon verstanden! werde natürlich in Zukunft die von
    dir vorgeschlagen Funktion sleep verwenden. sleep(1) hatte Ich auch ausprobiert.. es wartet allerdings eine Minute zwischen den Worten... das man
    so eine Schleife nicht beim echten Programmieren als Wartezeit benutzt ist mir
    klar! Ich werde mir die Arbeitsweise von sleep genauer anschauen... und es in dem Programm ersetzen ... Danke für eure Tips!

    sleep ist halt keine portable Funktion und kann je nach Plattform was anderes machen (bei Linux wartet es z.B. Sekunden, bei Windows in Millisekunden), aber ein sleep, das in Minuten wartet ist mir neu. Gibt bestimmt auch andere Funktionen dieser Art auf der Plattform (unter Linux gibt es z.B. usleep, wenn man weniger als 1 Sekunde warten möchte).



  • Jepp, Danke für den Hinweis!



  • Da es nicht portabel ist, heißt es dann auch mal sleep oder Sleep 🙄


Anmelden zum Antworten