Jedes x.te Element aus einer Datenmenge



  • Hallo,

    habe da ein Logikproblem, bei dem mir bisher der rechte Ansatz fehlt.

    Folgende Fragestellung:
    Aus einer Menge von n Elementen möchte ich jedes x.te auslesen.

    a) dabei soll das erste und letzte Element in jedem Fall enthalten sein und
    b) sollte n nicht durch x teilbar sein, müsste eine Anpassung vorgenommen werden, um eine 'einigermaßen' harmonische Verteilung zu erreichen.

    Beispiel: 10 Elemente, jedes 2. soll gelesen werden.
    D.h. folgende Elemente würden gelesen: 0, 2, 4, 6, 9.

    Erläuterung:
    Da das erste und letzte 'Pflicht' sind, also 0 und 9, muss das rechnerisch ermittelte 8. um 1 verändert werden.

    Ich hoffe, das Beispiel macht das Problem deutlich.

    Hoffe auf Antwort.

    Lieben Gruß
    Leo



  • Eine einfache Methode waere den index nicht als integer zu nehmen, sondern als Fliesskomma-Zahl und diese immer zu runden.

    Also sowas in der Art:

    const int n = 10;
    int a[n] = { 0, ..., 9 };
    for(int i = 0; i < k; ++i) {
      double index = i / (k - 1.0) * (n - 1.0);
      do_something(a[int(index + 0.5)]);
    }
    


  • Hi Christoph,

    sieht kompakt aus. Habe nur keine Ahnung, wofür k steht bzw. was ich dafür einsetzen soll.

    Gruß
    Leo



  • k ist die Anzahl der Elemente, die du auswaehlen moechtest. Wenn du also ungefaehr jedes x-te Element aus einer Liste der Laenge n auswaehlen moechtest, moechtest du vielleicht k = n / x Elemente insgesamt haben.



  • Hi Christoph,

    bin tief beeindruckt! It works. Und das mit 1/4 des Codes, den ich gebraucht hatte.

    Jetzt kann ich mit Deinern Hilfe und der von Herrn De Casteljau die schönsten Bezierkurven zeichnen UND skalieren.

    Liebe Grüße
    Leo



  • gings nicht einfach mit modulo?

    int a[10] = {...}
    int x_te = 4
    for(int i=0,i<k;++i)
     if(i%xte = 0)
       // mach was mit jedem xtren
    


  • Ohne Flieskomma Zahlen geht es auch. Sei n die Anzahl der Elemente und x die Anzahl der Elemente die du rausnehmen willst. Nehmen wir mal an es gäbe Brüche und diese könntest du als Index verwenden:

    for(Bruch i=0; i<=n-1; i += (n-1)/(x-1))
        ...mach was mit a[i]...
    

    Es muss i<=n-1 weil n-1 der größt mögliche Index ist. Das normale i<n würde nicht gehen da i nicht unbedingt ganzzahlig ist und somit ist i<n nicht äquivalent zu i<=n-1. x-1 weil wir um x Indices zu bekommen x-1 mal inkrementieren müssen. Den ersten Index kriegen wir mit 0 ja bereits ohne Inkrementierung.

    Da es aber keine Brüche gibt multiplizieren wir einfach alles mit x-1 durch

    for(unsigned i=0; i<=(n-1)*(x-1); i += n-1){
    	int abgerundet = i/(x-1);
    	int aufgerundet = (i + x-2)/(x-1);
    	int normal_gerundet = (i + (x-1)/2)/(x-1);
    }
    

    Das geht sogar wenn x > n. In dem Fall werden aber Elemente mehrfach ausgewählt.

    Das einzige Problem an der Sache ist, dass (n-1)*x < 2^32 sein muss. Das ist in den meisten Fällen aber gegeben wenn du aber groß Listen hast und viele Elemente auswählst dann kann es schon mal zu einem Überlauf kommen. Die Lösung heißt dann unsigned long long.

    Die Ganzzahl Lösung ist schneller und genauer als die float Alternative un wahrscheinlich auch bei großen Listen besser geeignet. Ich muss aber gestehen, dass es mir schwer fällt das Verhalten von Fließkommazahlen in diesem Fall einzuschätzen. Für ein böses Erwachen sind diese aber leider all zu oft gut also Finger weg wenn es auch gut ohne geht.

    Edit: Damit meine Version klappt muss gelten n,x>=2 .
    EDIT2: Mit dem modulo geht das nicht da da nicht immer das letzte Element ausgewählt wird.


Anmelden zum Antworten