Schrittweite bei floating point austüfteln ???



  • Was du machen kannst:
    Zähl i von 0 bis 39564 in Schritten von 628. Dein Wert bei jedem Durchlauf ist dann x = (i - 19782) / 6300.0.

    Das sind dann genau 63 Schritte, wobei jeder Schritt 628/6300=0,099682539682539... ist.

    Ansonsten sollte auch diese wesentlich einfachere Variante genau genug für die allermeisten Anwendungen sein:

    #include <iostream>
     
    int main() {
        double const pi = 3.14; // oder auch gern genauer
        double const step = 2.0 * pi / 60.0;
        double const start = -pi;
        for (int i = 0; i <= 60; i++) {
            double const x = start + step * i;
            std::cout << x << "\n";
        }
    }
    

    https://ideone.com/jLQc2Z



  • @hustbaer sagte in Schrittweite bei floating point austüfteln ???:

    @Bushmaster sagte in Schrittweite bei floating point austüfteln ???:

    was auch noch ginge ist mit integer von -314 bis +314 zählen, mit schrittweite von 10, dann nach float casten und durch 100.0 teilen.
    das ist mir kurz danach eingfallen nachdem ich die frage stellte. immer erst ne minute nachdenken bevor man fragt. aber so hattet ihr auch euren spaß. 🙂
    und ich habe mich als noob geoutet.

    Wie soll das gehen?

    -314
    -304
    ...
    -  4
    +  6
    ...
    +306
    +316
    

    Punktlandung ist das keine.

    mit der angepassten schrittweite. 2*314, d.h 628 hat 4 als teiler, also nimmt man 4 als schrittweite. das macht 157 werte.
    dann landet man wieder auf'm punkt.
    sind das zu viele dann schmeißt man jeden zweiten raus. hauptsache der erste und letzte beiben erhalten.
    es geht um das plotten von kurven auf einem kleinen display. diese kurven haben alle eine wellenlänge von 2 pi.



  • @hustbaer sagte in Schrittweite bei floating point austüfteln ???:

    double const pi = 3.14; // oder auch gern genauer
    double const step = 2.0 * pi / 60.0;
    double const start = -pi;
    for (int i = 0; i <= 60; i++) {
    double const x = start + step * i;
    std::cout << x << "\n";
    }

    das gefällt mir sehr.


  • Mod

    @Bushmaster sagte in Schrittweite bei floating point austüfteln ???:

    es geht um das plotten von kurven auf einem kleinen display. diese kurven haben alle eine wellenlänge von 2 pi.

    Moment mal. Das passt aber gar nicht zu deiner Frage. Wenn mit endlichen Pixeln plottest, kannst du schließlich nicht die Schritte wählen, wie es dir passt, sondern du musst ausrechnen, welchen x-Wert jeder Pixel repräsentiert.



  • @SeppJ sagte in Schrittweite bei floating point austüfteln ???:

    @Bushmaster sagte in Schrittweite bei floating point austüfteln ???:

    es geht um das plotten von kurven auf einem kleinen display. diese kurven haben alle eine wellenlänge von 2 pi.

    Moment mal. Das passt aber gar nicht zu deiner Frage. Wenn mit endlichen Pixeln plottest, kannst du schließlich nicht die Schritte wählen, wie es dir passt, sondern du musst ausrechnen, welchen x-Wert jeder Pixel repräsentiert.

    das display ist 200 pixel breit. ein paar buttons sollen auch noch drauf.


  • Mod

    @Bushmaster sagte in Schrittweite bei floating point austüfteln ???:

    @SeppJ sagte in Schrittweite bei floating point austüfteln ???:

    @Bushmaster sagte in Schrittweite bei floating point austüfteln ???:

    es geht um das plotten von kurven auf einem kleinen display. diese kurven haben alle eine wellenlänge von 2 pi.

    Moment mal. Das passt aber gar nicht zu deiner Frage. Wenn mit endlichen Pixeln plottest, kannst du schließlich nicht die Schritte wählen, wie es dir passt, sondern du musst ausrechnen, welchen x-Wert jeder Pixel repräsentiert.

    das display ist 200 pixel breit. ein paar buttons sollen auch noch drauf.

    Und? Ich glaube, du verstehst meinen Einwand nicht. Du gehst dein Problem verkehrt herum an und hast genau die falsche Frage gestellt.



  • @SeppJ sagte in Schrittweite bei floating point austüfteln ???:

    @Bushmaster sagte in Schrittweite bei floating point austüfteln ???:

    @SeppJ sagte in Schrittweite bei floating point austüfteln ???:

    @Bushmaster sagte in Schrittweite bei floating point austüfteln ???:

    es geht um das plotten von kurven auf einem kleinen display. diese kurven haben alle eine wellenlänge von 2 pi.

    Moment mal. Das passt aber gar nicht zu deiner Frage. Wenn mit endlichen Pixeln plottest, kannst du schließlich nicht die Schritte wählen, wie es dir passt, sondern du musst ausrechnen, welchen x-Wert jeder Pixel repräsentiert.

    das display ist 200 pixel breit. ein paar buttons sollen auch noch drauf.

    Und? Ich glaube, du verstehst meinen Einwand nicht. Du gehst dein Problem verkehrt herum an und hast genau die falsche Frage gestellt.

    ja, die frage war totaler mist.



  • @TGGC sagte in Schrittweite bei floating point austüfteln ???:

    Nie mit float zählen, wenn es irgendwie nachvollziehbares Ergebnis sein soll. Zähle mit einem int die Anzahl der Schritte die du haben willst (z.b. 6.3/0.1 = 63) und lerpe mit i/(max -1) zwischen den Werten.

    Bitte nimm genau diese Lösung und nimm als Schrittzahl die gewünschte Anzahl Pixel.



  • @TGGC ja, genau so.

    Man sollte vielleicht noch erwähnen, dass man so eventuell Löcher im Kurvenplot erhält, wenn man einfach nur die Pixel an den ausgerechneten (x, y)-Koordinaten setzt.

    Das passiert z.B., wenn die Kurve in y-Richtung schneller ist als in x-Richtung (z.B. zwei Pixel nach oben für einen Pixel nach rechts).

    Simple Lösung ist keine einzelnen Pixel zu zeichnen, sondern stattdessen gerade Linien zwischen einem Kurvenpixel und seinem Vorgänger. Da kann einem da z.B. der gute alte Jack Bresenham weiterhelfen. Den Algo sollte man ohnehin irgendwo am Start haben, wenn man das Display schon pixelweise selbst programmieren muss 😉


  • Mod

    Darauf kommt Kollege Bushmaster hoffentlich auch, spätestens wenn er den ersten Plot sieht. Interessanter ist aber das Problem, dass man bei einer geringen Auflösung leicht einen Sampling-Error bekommen kann. Mit 200 Punkten erfasst man evtl. gar nicht die Extrempunkte, die für die Characterisierung wichtig sind, sondern zeichnet eine völlig andere Kurve.

    Wenn er was von 2π-Periode schreibt, sind das wahrscheinlich irgendwelche Schwingungen, die er darstellen möchte. Da ist das Problem oft sogar besonders verstärkt, weil man dann irgendwelche Muster bekommt, die gar nichts mit der Realität zu tun haben, aber bedeutsam aussehen.

    So weit ich weiß ignorieren viele Plotprogramme das Problem (ist halt auch nicht so einfach zu lösen), aber gerade bei geringen Auflösungen ist es relevanter.



  • @SeppJ sagte in Schrittweite bei floating point austüfteln ???:

    Wenn er was von 2π-Periode schreibt, sind das wahrscheinlich irgendwelche Schwingungen, die er darstellen möchte. Da ist das Problem oft sogar besonders verstärkt, weil man dann irgendwelche Muster bekommt, die gar nichts mit der Realität zu tun haben, aber bedeutsam aussehen.

    Zumindest Aliasing-Artefakte lassen sich nach Nyquist–Shannon vermieden, wenn man sicherstellt, dass in jeder Periode mindestens 2 Abtastpunkte liegen. Dann hat man zumindest keine Frequenzen in der Abbildung, die da nicht reingehören. Die Amplituden können aber dennoch etwas komisch sein, je nachdem, welche Punkte man erwischt. Schön wäre z.B. bei der Sinusfunktion zumindest die Extremwerte mit +1/-1 voll drin zu haben.

    So weit ich weiß ignorieren viele Plotprogramme das Problem (ist halt auch nicht so einfach zu lösen), aber gerade bei geringen Auflösungen ist es relevanter.

    Man möge mich korrigieren, aber ich glaube das lässt sich effektiv nur lösen, indem man den Plot in (für die darin enthaltenen Frequenzen) ausreichend hoher Auflösung im Speicher zeichnet und das dan auf die Display-Auflösung heruntersampelt (hochaufgelöstes Bild z.B. mit Gauss-Filter bandbegrenzen und dann auf Ziel-Auflösung herunterskalieren [Supersampling]).

    Das wird aber schnell aufwändig, und ist für die Anforderungen von @Bushmaster sicher erstmal Overkill 😉


  • Mod

    @Finnegan sagte in Schrittweite bei floating point austüfteln ???:

    @SeppJ sagte in Schrittweite bei floating point austüfteln ???:

    Wenn er was von 2π-Periode schreibt, sind das wahrscheinlich irgendwelche Schwingungen, die er darstellen möchte. Da ist das Problem oft sogar besonders verstärkt, weil man dann irgendwelche Muster bekommt, die gar nichts mit der Realität zu tun haben, aber bedeutsam aussehen.

    Zumindest Aliasing-Artefakte lassen sich nach Nyquist–Shannon vermieden, wenn man sicherstellt, dass in jeder Periode mindestens 2 Abtastpunkte liegen. Dann hat man zumindest keine Frequenzen in der Abbildung, die da nicht reingehören. Die Amplituden können aber dennoch etwas komisch sein, je nachdem, welche Punkte man erwischt. Schön wäre z.B. bei der Sinusfunktion zumindest die Extremwerte mit +1/-1 voll drin zu haben.

    Jupp. Aber das weiß ja das allgemeine Plotprogramm nicht 🙂
    Und wie du selbst sagst, ist das höchstens ausreichend, damit ein Computer ein Signal (innerhalb gewisser Schranken) rekonstruieren kann, aber das heißt noch nicht, dass es gut aussieht. Ich weiß auch keine tolle Lösung. Habe so einiges gesehen, was mal mehr oder weniger gut geht. Ich würde es auch erst einmal ignorieren, aber unbedingt daran denken, sobald die erste Kurve komisch aussieht.



  • @Finnegan Ich glaube eine häufige Variante ist es in jeder Pixelspalte eine vertikale Linie von min bis max der von dieser Pixelspalte abgedeckten Samples zu machen. Dadurch bekommst du dann einen fliessenden Übergang zwischen "Waveform" und dieser Darstellung mit den Knubbeln/dem dicker und dünner werdenden Balken bzw. wie auch immer man es nennen möchte.



  • Das Nyquist–Shannon Theorem bringt hier grad mal null. Wenn man einfach nur die Punkte zeichnet bzw. die dann noch linear interpoliert, fügt man nämlich noch neue Frequenzen hinzu (man hat dann Rechteck/Sägezahnwellen). Das Theorem sagt lediglich aus, das es nur eine einzige Funktion gibt, die man aus kleineren Frequenzen bauen kann, die dann genau durch alle Punkte geht. Und die Visualisierung zeigt eben nicht diese Funktion.



  • also wenn ich als schrittweite (3.14 - -3.14) / 200 nehme, erhalte ich als endpunkt für double 3.14000000000001 und für float 3.13999581336975. reicht doch, oder?



  • @TGGC sagte in Schrittweite bei floating point austüfteln ???:

    Das Nyquist–Shannon Theorem bringt hier grad mal null. Wenn man einfach nur die Punkte zeichnet bzw. die dann noch linear interpoliert, fügt man nämlich noch neue Frequenzen hinzu (man hat dann Rechteck/Sägezahnwellen).

    Ich meinte damit nicht, dass die so dargestellten Kurven dann eine vollständige, korrekte Rekonstruktion sind, sondern dass wenn ich mit dieser Methode z.B. eine Sinusfunktion darstelle, diese auch tatsächlich eine Periode von 2π zeigt und nicht 4π oder sowas - wenn auch ziemlich eckig angenähert. Das hätte ich vielleicht deutlicher einschränken sollen.

    Es stimmt allerdings, dass das nur etwas darüber aussagt, wie breit ich eine Periode der Kurve minimal darstellen kann, ohne dass es wegen Aliasing aussieht, als wäre es eine sinusförmige Welle mit völlig anderer Frequenz.



  • Erstmal bin ich der Meinung, das du was Anderes gesagt hast.

    Und Dir ist klar, das nur 3 Punkte der gesamte Kurve genommen werden nach deinem Vorschlag? Und das wären dann -1,0,1 bei -Pi/2, 0, Pi/2. Das sieht einfach nach einer steigenden Gerade aus, kaum jemand wird im Kopf daraus die Sinusfunktion rekonstruieren können.



  • @Finnegan sagte in Schrittweite bei floating point austüfteln ???:

    Ich meinte damit nicht, dass die so dargestellten Kurven dann eine vollständige, korrekte Rekonstruktion sind, sondern dass wenn ich mit dieser Methode z.B. eine Sinusfunktion darstelle, diese auch tatsächlich eine Periode von 2π zeigt und nicht 4π oder sowas - wenn auch ziemlich eckig angenähert. Das hätte ich vielleicht deutlicher einschränken sollen.

    ich denke so lange die grafik etwa 3 mal so breit wie hoch ist, geht das so. ich habe keine komplizierten wellenformen, bloß sinus, dreieck, rechteck, trapezförmig, sägezahn und ähnliche spielereien, die sich aus nem sinus berechnen lassen. es ist ein hobby-projekt, animiert durch dieses video: https://www.bitchute.com/video/gvHWPCpZfDmI/
    dieser mensch zählt übrigens eine double-variable hoch. 🙂



  • @hustbaer sagte in Schrittweite bei floating point austüfteln ???:

    @Finnegan Ich glaube eine häufige Variante ist es in jeder Pixelspalte eine vertikale Linie von min bis max der von dieser Pixelspalte abgedeckten Samples zu machen. Dadurch bekommst du dann einen fliessenden Übergang zwischen "Waveform" und dieser Darstellung mit den Knubbeln/dem dicker und dünner werdenden Balken bzw. wie auch immer man es nennen möchte.

    diese lücken und verdickungen sehe ich auch. vielleicht mache ich aus plot(x,y) ein drawto(x,y). mal sehen ...



  • @TGGC sagte in Schrittweite bei floating point austüfteln ???:

    Erstmal bin ich der Meinung, das du was Anderes gesagt hast.

    In Bezug auf die von SeppJ erwähnten Probleme bei Kurvenplots mit nur so wenigen Punkten habe ich geschrieben, dass sich damit "zumindest (die) Aliasing-Artefakte vermeiden lassen" (nicht alle Probleme). Das ist insofern mehrdeutig, als dass es hier zwei Phänomene gibt, wo man dieses Aliasing beobachten kann: Einmal die "Pixeltreppchen" als Aliasing der in dem erzeugten 2D-Bild überlagerten Frequenzen (was du wohl meintest). Zum anderen die falschen Frequenzen, die entstehen können, wenn man die sinusförmige Kurve mit zu wenig Pixeln in der Breite darstellt. Das ist alles, wo ich hier drauf hinaus wollte. Ich nenne auch den Blechsound, den man erhält, wenn man Audio mit zu niedriger Rate abtastet "Aliasing-Artefakte".

    Und Dir ist klar, das nur 3 Punkte der gesamte Kurve genommen werden nach deinem Vorschlag? Und das wären dann -1,0,1 bei -Pi, 0, Pi. Das sieht einfach nach einer steigenden Gerade aus, kaum jemand wird im Kopf daraus die Sinusfunktion rekonstruieren können.

    Ja, und wenn ich einen Ausschnitt der Kurve betrachte, der nur eine Höhe und keine Breite hat, dann sieht die Kurve wie ein einziger Punkt aus. Wenn du diese "Gerade" nämlich weiterzeichnest, dann erhältst du eine hübsche Sägezahnwelle mit einer Periode von eben 2π und nicht 42π. So banal ist das, wo ich drauf hinaus wollte und ich hatte nicht vor, das so ausarten zu lassen. Deine Interpretation ist zwar sehr naheliegend, war mir aber tatsächlich in dem Moment nicht bewusst, als ich das so formuliert habe.


Anmelden zum Antworten