Nicht lineare "progressbar" % berechnen

Dampfbox schrieb:
Verwirrend ist allenfalls deine im Startpost skizzierte Verwendung von "Prozent", obwohl es nicht um Prozent geht.
Verwirrend finde ich daran gar nix. Der Füllgrad F (in Prozent) hängt von einer Eingangsvariable x ab.
Damit ergibt sich eine Funktion F(x). Die Frage ist nur, wie F(x) sinnvoll für den Verwendungszweck aussehen kann.
 
  • Gefällt mir
Reaktionen: Raijin, machhommy und tollertyp
Nilson schrieb:
Verwirrend finde ich daran gar nix. Der Füllgrad F (in Prozent) hängt von einer Eingangsvariable X ab.
Damit ergibt sich eine Funktion F(x).
Verwirrend daran (also ein seiner Eingangsskizze aus Post #1) ist, dass Prozente linear sind, er aber eine nichtlineare Progression abzubilden versucht.

Einfach die Prozente weglassen und alles ist gut (z.B. so wie in seiner jsfiddle-Skizze)
 
Wie groß kann p denn werden?

Evtl. einfach eine Lookup-Tabelle (Array) basteln
 
P ist der Warenkorbwert und hat somit theoretisch keine Grenze aber ab 100 spielt es keine Rolle mehr, weil damit eh der maximale Bonus/Meilenstein erreicht ist und ich den Balken dann komplett füllen kann.

Ganz blöd gesagt if p >= 100 fülle den Balken komplett.
 
Wieso dann die Einheit "Punkte" einführen, wenn der Kunde die nicht sieht?
Einfach intern mit Prozenten rechnen, denn jeder deiner Milestones ist ein Prozentsatz von 100€ bzw. lässt sich als solcher abfragen.

Hier deine Milestones zum Mitschreiben:
17%
50%
83%
100%

Oder in Euro ausgedrückt:
17€
50€
83€
100€

Übrigens wäre es schlau gewesen, im Startpost direkt von Euro zu sprechen, wenn sowieso Euros gemeint sind.

Das schlimmste hier bleibt aber die Eingangsskizze, die "100 Punkte" bei 83% zeigt und danach bis 100% weiter geht....
 
Dampfbox schrieb:
Das schlimmste hier bleibt aber die Eingangsskizze, die "100 Punkte" bei 83% zeigt und danach bis 100% weiter geht....
Ich als Normal-Mathematiker sehe das so nicht. 0 - 100% sind doch nur Optik. 50% zu erreichen soll optisch vorgaukeln man hat mit dem jetzigen Füllstand des Warenkorbes die Hälfte des Gesamtbonus erreicht und man braucht nur noch mal ebenso viel, um den höchsten Bonus zu erreichen. Deshalb empfinde ich die exponentielle Berechnung von @Nilson als logisch. Natürlich werden dann keinerlei Zahlen dort zu sehen sein. Oder sehe ich da irgend was falsch?
 
  • Gefällt mir
Reaktionen: Raijin, machhommy, KitKat::new() und eine weitere Person
Mit e^x erreicht man nie das Ende, aber das kann man erreichen oder sogar überschreiten
machhommy schrieb:
P ist der Warenkorbwert und hat somit theoretisch keine Grenze aber ab 100 spielt es keine Rolle mehr
Also ist e^x nicht gut.

Im Endeffekt brauchst du eine Funktion, die einen Wert in € auf die % mapped. Das kann entweder irgendein Polynom sein (dann ist es "glatt") oder auch irgend etwas beliebiges.

Weil mir gerade langweilig ist, hier nen Fiddle: https://jsfiddle.net/jd43vr6z/32/
 
  • Gefällt mir
Reaktionen: machhommy
Man kann ja einfach beim Umrechnen p auf 100 begrenze mit Math.min(p, 100) - bzw. noch besser wäre es ja, es einfach anhand des höchst möglichen Wertes zu limitieren, wie gesagt, sinnvoll das Modell im Speicher zu haben, dann kann man den Maximalwert auch aus dem Modell ziehen.

Dampfbox schrieb:
Das schlimmste hier bleibt aber die Eingangsskizze, die "100 Punkte" bei 83% zeigt und danach bis 100% weiter geht....
Nicht nur in dem Punkt unterscheiden sich unser Ansichten...
 
Dampfbox schrieb:
Einfach intern mit Prozenten rechnen, denn jeder deiner Milestones ist ein Prozentsatz von 100€ bzw. lässt sich als solcher abfragen.

Hier deine Milestones zum Mitschreiben:
17%, 50%, 83%, 100%

Oder in Euro ausgedrückt:
17€, 50€, 83€, 100€

Nein es gibt keinen Milestone bei 17 € und bei 83 €. Es gibt 3 Meilensteine, bei 20 €, 50 € und 100 € Warenkorbwert. Irgend was scheinst du nicht zu verstehen denke ich. Und nein der 20 € Milestone sitzt nicht bei 20 % auf der Leiste.

Dampfbox schrieb:
Übrigens wäre es schlau gewesen, im Startpost direkt von Euro zu sprechen, wenn sowieso Euros gemeint sind.

Das spielt doch in dem Fall gar keine Rolle. Ob Punkte, Euros oder Kartoffeln, es ist für das Problem völlig unerheblich. Die Einheiten sind völlig irrelevant innerhalb der mathematischen Berechnung.

Dampfbox schrieb:
Das schlimmste hier bleibt aber die Eingangsskizze, die "100 Punkte" bei 83% zeigt und danach bis 100% weiter geht....

Das ist doch murks was du da schreibst. Die Leiste hat logischerweise 100 %. Es gibt 3 Meilensteine und diese Meilensteine die bei 20 €, 50 € und 100 € erreicht werden, sitzen eben nicht auf Ihren passend Prozentstellen, weil ich diese nicht mathematisch sondern optisch auf dieser Leiste verteilt habe. Und um genau das (optisch) zu verdeutlichen habe ich eben die % eingezeichnet.

Ist doch nicht so schwer zu verstehen oder bin ich blöd? :confused_alt:
Egal reicht für heute. Morgen geht es weiter.
 
  • Gefällt mir
Reaktionen: tollertyp
Dampfbox schrieb:
Verwirrend daran (also ein seiner Eingangsskizze aus Post #1) ist, dass Prozente linear sind, er aber eine nichtlineare Progression abzubilden versucht.
Der Prozentsatz bezieht sich auf die Länge des Balkens (den Füllgrad). Da muss nichts weggelassen werden. Die Skizze ist wunderbar.
 
  • Gefällt mir
Reaktionen: tollertyp
Ich denke, du suchst die Ableitung der Sigmoidfunktion. Hier einmal leicht modifiziert:

(-4 ℯ^(2x)) / (1 + ℯ^(2x))² + 1

1654647064356.png


In der Mitte bei 50"%" soll die Schrittweite fast 0"%" betragen, und an den Rändern fast 1"%". Das leistet die Sigmoidfunktion. Ich glaube, man nennt das auch logarithmische Skalierung. Vgl. https://de.wikipedia.org/wiki/Logarithmische_Darstellung .
 
Gee858eeG schrieb:
Der Prozentsatz bezieht sich auf die Länge des Balkens (den Füllgrad)
Und ab 83 Punkte
machhommy schrieb:
Die Leiste hat logischerweise 100 %. Es gibt 3 Meilensteine und diese Meilensteine die bei 20 €, 50 € und 100 € erreicht werden, sitzen eben nicht auf Ihren passend Prozentstellen, weil ich diese nicht mathematisch sondern optisch auf dieser Leiste verteilt habe. Und um genau das (optisch) zu verdeutlichen habe ich eben die % eingezeichnet.
Wenn der Letzte Milestone bei 100€ Warenkorbwert sitzt, warum geht dann die Leiste weiter?

Dahinter kommt doch nichts mehr. 100€ sind 100% der erreichbaren Milestones, warum sitzt der 100€-Milestone dann bei dir bei 83% der Leiste?
Ergänzung ()

Ham Burger schrieb:
0 - 100% sind doch nur Optik. 50% zu erreichen soll optisch vorgaukeln man hat mit dem jetzigen Füllstand des Warenkorbes die Hälfte des Gesamtbonus erreicht
Tut es aber nicht, da man bereits bei 83% Leistenfüllung den Gesamtbonus erreicht
 
CyborgBeta schrieb:
Ich denke, du suchst die Ableitung der Sigmoidfunktion. Hier einmal leicht modifiziert:

(-4 ℯ^(2x)) / (1 + ℯ^(2x))² + 1

Anhang anzeigen 1225907

In der Mitte bei 50"%" soll die Schrittweite fast 0"%" betragen, und an den Rändern fast 1"%". Das leistet die Sigmoidfunktion. Ich glaube, man nennt das auch logarithmische Skalierung. Vgl. https://de.wikipedia.org/wiki/Logarithmische_Darstellung .

Wer soll das später warten und was passiert wenn ein neuer Milestone dazu kommt?

Ich find die Lösung mit den Segmenten schon nicht schlecht, da brauchste nur eine Funktion die die Segmente zeichnet und ein Array wo du die Milestones bzw Infos dazu ablegst dann kannst du das schön mit Dreisatz berechnen. Und wenn dann in 2 Jahren mal jemand ankommt und möchte das erweitert haben guckt dein Azubi einmal auf den Code und erweitert das Array. PLUS es sind auch grafisch drei Segmente, das heisst die können einfach umbrechen wenn der Platz nicht reicht....
 
  • Gefällt mir
Reaktionen: tollertyp, Murray B. und KitKat::new()
Naja, ich stelle mir das so vor:

1654684907716.gif


Die Funktionen dazu sehen so aus (hier einmal in Java):

Java:
    public static double f(int x, double b) {
        x = x - 50;
        double a = 0.25;
        b = 1.16015625;
        return (-4 * Math.pow(Math.E, a * x)) / Math.pow(1 + Math.pow(Math.E, a * x), 2) + b;
    }

    public static double g(int x, double b) {
        double sum = 0;
        for (int i = 0; i < x; i++) {
            sum += f(i, b);
        }
        return sum;
    }

Die Parameter (a und b) lassen sich natürlich beliebig anpassen, je nachdem, wie steil/flach das Ganze sein soll.

Man sieht, dass die ProgressBar "in der Mitte" wesentlich langsamer läuft als an den Rändern.
 
Dampfbox schrieb:
warum sitzt der 100€-Milestone dann bei dir bei 83% der Leiste?

Wie oft denn noch? Weil ich die Meilensteine auf der Leiste genau so verteilen möchte. Das habe ich ca. 5 mal erklärt ... du scheinst etwas schwer von Begriff zu sein. Lassen wir das einfach.

An alle anderen, vielen Dank für die Hilfe. Ich werde mir jetzt nach und nach die unterschiedlichen Ansätze anschauen und am Ende eine Rückmeldung geben.

Die Polynominterpolation Variante von @Nilson funktioniert schon mal ganz gut. Danke dir :)

Javascript:
var x = 50;
var log = (129*x)/200 + (247*x**2)/20000 - (21*x**3)/200000
 
Zuletzt bearbeitet:
Mir hat das jetzt doch keine Ruhe gelassen und ich hab noch mal "optimale" Werte für die Funktion gesucht...

Die Funktion sieht nun so aus:

Java:
    public static double f1(int x) {
        x = x - 50;
        double a = 0.1;         // Weite der Öffnung
        double b = 1.591962021; // Höhe
        double c = -6;          // Tiefe der Öffnung
        return (c * Math.pow(Math.E, a * x)) / Math.pow(1 + Math.pow(Math.E, a * x), 2) + b;
    }

    public static double f2(int x) {
        double sum = 0;
        for (int i = 0; i < x; i++) {
            sum += f1(i);
        }
        return sum;
    }

Wertetabelle für f2 (gekürzt):

Code:
0    0,00
...
10    15,27
...
20    29,51
...
30    41,30
...
40    48,51
...
50    50,73
...
60    52,63
...
70    59,29
...
80    70,72
...
90    84,79
...
100    100,00

a und c lassen sich beliebig wählen, je nachdem welche Form die Kurve denn haben soll.

Den Wert für b kannst du einfach rechnerisch ermitteln (Intervallhalbierung), Beispiel:

Java:
    public static double f3(int x, double b) {
        x = x - 50;
        double a = 0.1;
        double c = -6;
        return (c * Math.pow(Math.E, a * x)) / Math.pow(1 + Math.pow(Math.E, a * x), 2) + b;
    }

    public static double f4(int x, double b) {
        double sum = 0;
        for (int i = 0; i < x; i++) {
            sum += f3(i, b);
        }
        return sum;
    }

    public static double calcB() {
        double b1 = 0.5;    // Min
        double b2 = 4;      // Max
        double b3 = (b1 + b2) / 2;
        double last = 0;
        while (true) {
            double g = f4(100, b3);
            if (Math.abs(g - 100) == last) {
                System.out.println("b3 = " + b3);
                System.out.println("g = " + g);
                break;
            }
            last = Math.abs(g - 100);
            if (g < 100) {
                b1 = b3;
            } else {
                b2 = b3;
            }
            b3 = (b1 + b2) / 2;
        }
        return b3;
    }

Für die ProgressBar bekomme ich schließlich das folgende Bild:

1654700598721.gif


Ich bin mir aber nicht zu 100 % sicher, ob es nicht auch eine einfache Logarithmusfunktion tun würde, oder ob man die Eulersche Zahl hierbei überhaupt benötigt...

Du kannst ja den Ansatz wählen, der dir am meisten zusagt bzw. gefällt - und diesen dann in JS implementieren.
 
Also die mathematischen Formeln die @Nilson und CyborgBeta angesprochen haben mögen ein schöneres Ergebnis liefern, aber ich bin eher pragamtisch unterwegs und mir ist da die Wartungsfreundlichkeit/Nachvollziehbarkeit wichtiger.
 
@tollertyp Bist du jetzt der TE? Wenn nicht, warum mischt du dich dann ein? Verstehe ich gerade nicht...

Aber zum Argument... Wenn die Funktion einmal steht und sauber implementiert und dokumentiert wurde, dann gibt es daran überhaupt nichts zu warten.

Dass das vielleicht keine angemessene Anforderung für einen Azubi ist, ist mir eigentlich relativ egal... Hier wurde eine Frage gestellt, ein User-Case beschrieben, und ich habe versucht, darauf bestmöglich zu antworten.

Wir heulen alle eine Runde rum, weil Mathe Sch**** ist, hilft dabei niemandem. jm2c.
 
CyborgBeta schrieb:
Wenn nicht, warum mischt du dich dann ein? Verstehe ich gerade nicht...
Wenn du dich daran störst, dass jemand von der Seite seine valide Meinung zu einem Thema kundtut, bist du in einem öffentlichen Forum vielleicht nicht am besten aufgehoben.
 
  • Gefällt mir
Reaktionen: tollertyp und Gee858eeG
Zurück
Oben