Hallo Forenmitglieder,
ich bastle für die Modellbahn an einem Heißläuferortungsgerät. Da im
Modell überhitzte Achslager (hoffentlich) nie auftreten, möchte ich eine
Möglichkeit finden, pseudo-zufällige Zahlen in der Auswertung zu nutzen.
Ich habe mir das momentan so überlegt:
1 | #define PERCENTAGE 200 // Gesamtzahl an Achsen, bis Ereignis wieder auftritt
| 2 | #define MAX_ANZAHL 3 // maximale Anzahl an Fehlern pro einzelnen Zug
| 3 |
| 4 | unsigned int axle_count; //zählt die Achsen eines einzelnen vorbeifahrenden Zuges
| 5 | unsigned int global_axles; //zählt Achsen aller Züge
| 6 |
| 7 | unsigned char fehleranzahl; // Anzahl an Fehlern pro untersuchten Zug
| 8 | unsigned int fehler[MAX_ANZAHL]; //Array, wo Fehler gespeichert werden
| 9 |
| 10 | ...
| 11 |
| 12 | if (global_axles >= PERCENTAGE) // Ereignis tritt ein
| 13 | {
| 14 | /* Erzeuge Fehleranzahl so lange, bis kleiner der Maximalanzahl */
| 15 | while( fehleranzahl > MAX_ANZAHL)
| 16 | fehleranzahl = rand() / rand(); // Bruch, um Zahl zu verkleinern
| 17 |
| 18 | /* generiere Fehler innerhalb Zuglänge; 0 ist nicht zugelassen */
| 19 | for (uint8_t j=0; j< fehleranzahl; j++)
| 20 | {
| 21 | while( (j > axle_count) || (fehler[j] == 0))
| 22 | fehler[j] = rand();
| 23 | }
| 24 | global_axles = 0; // Setze Zähler wieder auf null
| 25 |
| 26 | } else fehleranzahl = 0;
| 27 |
| 28 | ...
|
Diese Methode erlaubt es mir nicht, eine prozentuelle Vorgabe zu machen,
wieviel Fehler produziert werden. Vorteilhaft ist aber die Zufälligkeit
der Anzahl, als auch der Position im Zug.
Gibt es eine Möglichkeit, die Gesamtzahl abzuschätzen (außer Probieren)?
Oder habt ihr andere Ideen?
Alternativ würde ich nur alle jede bei global_axles == PERCENTAGE
liegende Achse als fehlerhaft markieren, womit die Prozentualität
eindeutig festgelegt ist. Wäre halt nicht so schön.
Grüße
Michael Prader
Errata corrige:
Die while-Schleifen sind natürlich mit do-while-Schleifen zu ersetzen.
kopfschüttel
Eine weitere Möglichkeit ist mir eingefallen, und zwar folgende:
Falls global_axles >= PERCENTAGE ist, wird ein einzelner Fehler
generiert mit 1 | do {
| 2 | fehler = rand();
| 3 | } while (fehler > axle_count)
|
Ich verstehe nur Bahnhof...:]
Aber nur so am Rande solltest du
while( fehleranzahl > MAX_ANZAHL)
fehleranzahl = rand() / rand(); // Bruch, um Zahl zu verkleinern
mit
fehleranzahl = rand() % (MAX_ANZAHL + 1);
ersetzen, zumal du bei deiner version irgendwann eine Null im Nenner
stehen hast...crash.
Autsch, vielen Dank für den Hinweis, Maximilian.
Lg
Michael
Maximilian K. wrote:
> Ich verstehe nur Bahnhof...:]
Ich versuche, das Problem klarer darzustellen:
Ich habe ein Gerät gebaut, welches auf der Modellbahn die Achsen eines
vorbeifahrenden Zuges zählt.
Nun kommt es manchmal vor, dass Achsen wegen ungenügender Schmierung
heiß werden. Das kann schwere Folgen haben, sodass dies erkannt werden
muss. Das macht ein Heißläufer-Ortungsgerät.
Im Modell ist das natürlich nicht möglich, sodass hier per Zufall
gewisse Achsen als "überhitzt" deklariert werden sollen. Es ist
wünschenswert, die Prozentualität einzustellen, bezogen auf die
Gesamtmenge aller vorbeifahrenden Achsen (also n Züge mit jeweils i(n)
Achsen).
Mit der im ersten Posting genannten Methode wird zwar nur bei jeder
PERCENTAGE-Achse die Fehlerprozedur aufgerufen, es werden dabei aber von
0 bis MAX_ANZAHL viele Fehler generiert. Damit ist die Prozentualität
nicht mehr gegeben. Warum möchte ich mehrere Fehler in einem Zug? Weil
das in Echt schon mal vorkommen kann.
Vielleicht hat jemand eine Idee, wie ich die Prozentualität genauer
einhalten kann.
Ansonst generiere ich nur einen Fehler pro Zug. Wäre nicht ideal, aber
auch nicht so schlimm.
Lg
Danke
Michael Prader
Hallo,
nur eine kurze Überlegung:
Wenn Du 20% der Achsen Fehlerhaft haben willst, darf es bei der
Berechnung der fehlerhaften Achsen pro Zug keine 0 geben.
Eine fehlerhafte Achse wird immer zugelassen.
Zwei fehlerhafte Achsen immer nur in der hälfte der Fälle (An dieser
Stelle hättest Du dann Deine 0)
Drei fehlerhafte Achsen nur in 1/3 der Fälle
Gruß
Sven
Hallo Sven,
ich probiere mal folgendes, in der Hoffnung, dass es dem Sinn deiner
Überlegung entspricht:
1 | #define PERCENTAGE 200 // Gesamtzahl an Achsen, bis Ereignis wieder auftritt: Prozentualität 0.5 %
| 2 | #define MAX_ANZAHL 3 // maximale Anzahl an Fehlern pro einzelnen Zug
| 3 |
| 4 | unsigned int axle_count; //zählt die Achsen eines einzelnen vorbeifahrenden Zuges
| 5 | unsigned int global_axles; //zählt Achsen aller Züge
| 6 |
| 7 | unsigned char fehleranzahl; // Anzahl an Fehlern pro untersuchten Zug
| 8 | unsigned int fehler[MAX_ANZAHL]; //Array, wo Fehler gespeichert werden
| 9 |
| 10 | unsigned char total_events, double_event, triple_event; // Zähler für alle Ereignisse, für solche mit 2 Fehlern und 3 Fehlern
| 11 |
| 12 | ...
| 13 |
| 14 | if (global_axles >= PERCENTAGE) // Ereignis tritt ein
| 15 | {
| 16 | if (total_events >= 0xFF)
| 17 | {
| 18 | total_events = 0; double_event = 0; triple_event = 0;
| 19 | }
| 20 |
| 21 | total_events++; // erhöhe Gesamtzahl der Ereignisse
| 22 |
| 23 | /* Erzeuge Fehleranzahl so lange, bis kleiner der Maximalanzahl */
| 24 | do {
| 25 | fehleranzahl = rand() % (MAX_ANZAHL +1); // Bruch, um Zahl zu verkleinern
| 26 | } while( (fehleranzahl > MAX_ANZAHL) || (fehleranzahl == 0)) // Fehleranzahl 0 wird nicht zugelassen
| 27 |
| 28 | switch (fehleranzahl)
| 29 | {
| 30 | case 1: break; // 1 wird immer zugelassen
| 31 |
| 32 | case 2:
| 33 | if (double_event >= (total_events / 2)) fehleranzahl = 0;
| 34 | double_event++;
| 35 | break; // nur in Hälfte der Fälle zugelassen
| 36 |
| 37 | case 3: if (triple_event >= (total_events / 3)) fehleranzahl = 0;
| 38 | triple_event++;
| 39 | break; // nur in einem Drittel der Fälle zugelassen
| 40 |
| 41 | default: fehleranzahl = 0; break; // zur Sicherheit
| 42 | }
| 43 |
| 44 |
| 45 | /* generiere Fehler innerhalb Zuglänge; Achse 0 ist nicht zugelassen
| 46 | Die Wahrscheinlichkeit, dass zwei Fehler hintereinander gleich sind (an der selben Achse) wird nicht berücksichtigt
| 47 | */
| 48 | for (uint8_t j=0; j< fehleranzahl; j++)
| 49 | {
| 50 | do {
| 51 | fehler[j] = rand();
| 52 | } while( (fehler[j] > axle_count) || (fehler[j] == 0))
| 53 | }
| 54 |
| 55 | global_axles = 0; // Setze Zähler wieder auf null
| 56 |
| 57 |
| 58 |
| 59 | } else fehleranzahl = 0;
| 60 |
| 61 | ...
|
Verstehe ich das richtig, dass die Anzahl der doppelten und dreifachen
Ereignisse auch dann hochgezählt werden muss, wenn die Zahl selbst nicht
zugelassen wird?
Du musst folgendes machen:
rand() liefert dir eine Zufallszahl im Bereich 0 bis RAND_MAX
die alle gleich wahrscheinlich sind.
Du möchtest haben, dass eine fiktive Zahl mit einer gewissen
Wahrscheinlichkeit entweder 0 oder 1 ist (0 = kein Fehler,
1 = Fehler).
D.h. du rechnest dir eine Grenze aus. Liegt die Zahl die du
von rand() bekommst über dieser Grenze, dann ist deine
fiktive Zahl 0, liegt sie darunter oder ist sie gleich,
dann ist sie 1.
Diese Grenze liegt bei (RAND_MAX + 1 )* Fehlerwahrscheinlichkeit / 100
Mach mal ein Beispiel mit einer kleiner Zahl für RAND_MAX.
Sagen wir mal deine maximale Zufallszahl sei 20.
Du möchtest eine Fehlerwahrscheinlichkeit von 60%.
Die Grenze sei dann bei 21 * 60 / 100 = 12
In diesem hypotetischen Beispiel, kann rand() liefern
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20
Für jede dieser Zahlen bedeutet das
Zahl von rand() Zahl <= 12 -> daher fikitve Zahl
-------------------------------------------
0 ja 1
1 ja 1
2 ja 1
3 ja 1
4 ja 1
5 ja 1
6 ja 1
7 ja 1
8 ja 1
9 ja 1
10 ja 1
11 ja 1
12 ja 1
13 nein 0
14 nein 0
15 nein 0
16 nein 0
17 nein 0
18 nein 0
19 nein 0
20 nein 0
Von den 21 möglichen Ergebnissen, die du von rand() erhalten
kannst, führen 8 zu einem Ergebnis von 0, und 12 zu einem
Ergebnis von 1. Du hast daher eine Chance von 12 * 100 / 21
oder 57.1% dass das Ergebnis dieser Berechnung eine 1
(und du daher einen Fehler erzeugen willst) ist, da ja
rand() seine Zahlen nicht der Reihe nach, sondern zufällig
in irgendeiner Reihenfolge liefern wird.
int Border = Percent * ( (long)RAND_MAX + 1 ) / 100;
if( rand() <= Border ) {
generate_Error;
}
Ich habe jetzt nicht überprüft, wie es sich bei der obigen Lösung mit
der Wahrscheinlichkeit verhält.
Ich meinte es etwas anders, als ich es beschrieben habe.
1 | switch (fehleranzahl)
| 2 | {
| 3 | case 1: break; // 1 wird immer zugelassen
| 4 |
| 5 | case 2:
| 6 | if (double_event < 2))
| 7 | {
| 8 | fehleranzahl = 0;
| 9 | double_event++;
| 10 | }
| 11 | else
| 12 | {
| 13 | double_event = 0;
| 14 | }
| 15 | break; // nur in Hälfte der eintretenden Fälle zugelassen
| 16 |
| 17 | case 3:
| 18 | if (triple_event < 3))
| 19 | {
| 20 | fehleranzahl = 0;
| 21 | triple_event++;
| 22 | }
| 23 | else
| 24 | {
| 25 | triple_event = 0;
| 26 | }
| 27 | break; // nur in einem Drittel der auftretenden Fälle zugelassen
| 28 |
| 29 | default: fehleranzahl = 0; break; // zur Sicherheit
| 30 | }
|
Wenn man von der Wahrscheinlichkeit ausgeht, daß alle Fälle (1 Fehler, 2
Fehler, 3 Fehler) über einen großen Zeitraum in gleicher Anzahl
eintreten, bleibt die Summe der fehlerhaften Achsen in diesem Zeitraum
gleich.
> Du möchtest haben, dass eine fiktive Zahl mit einer gewissen
> Wahrscheinlichkeit entweder 0 oder 1 ist (0 = kein Fehler,
> 1 = Fehler).
Das ist nicht ganz korrekt. Ich möchte verschiedene Fehlerzahlen von 0-3
haben. Der Beitrag hat aber fürs praktische Verständnis genützt, danke.
@ Sven
Aha, der Unterschied zu meiner Version ist, dass ein zweifacher Fehler
nur bei seinem EIGENEN jeden zweiten Auftreten gültig ist. Ich hatte in
bei JEDEM zweiten Ereignis zugelassen, was falsch ist, das seh ich ein.
:-)
Tritt das Ereignis "2 Achsen" in deinem Code nicht erst beim 3. Mal auf?
(double_event < 2) ist bei 0 und 1 wahr, aber erst bei 2 unwahr. Das
gibt zwei:eins. Das ist ein (äußeres) Verhältnis von 3:1, und wenn ich
mich nicht täusche, würde damit es in nur einem Drittel der Fälle
auftreten.
Michael
jo da hast Du natürlich Recht, sorry.
Sven
Ok.
Vielen Dank für die wertvolle Hilfe!
Grüße
Michael
@ Karl Heinz Buchegger
Noch ein Nachtrag zum Thema:
In der Fragestellung bin ich ja davon ausgegangen, dass die
Fehlerroutine alle percentage-Achsen aufgerufen wird.
> Du musst folgendes machen:
>
> rand() liefert dir eine Zufallszahl im Bereich 0 bis RAND_MAX
> die alle gleich wahrscheinlich sind.
>
> Du möchtest haben, dass eine fiktive Zahl mit einer gewissen
> Wahrscheinlichkeit entweder 0 oder 1 ist (0 = kein Fehler,
> 1 = Fehler).
Dass bei deinem Verfahren alle Achsen unabhängig bewertet werden und die
(von mir aus Unverständnis gestellte) Bedingung, die Routine nur alle p
Achsen aufzurufen, gar nicht so elegant ist, habe ich erst jetzt
erkannt.
Insofern werde ich dein Verfahren einsetzen. Sollten doch mal mehr
Achsen pro Zug als erlaubt (Arraydimensionierung) auftreten (habe ich
auf 6 hinaufgeschraubt, damit ist die Wahrscheinlichkeit im
1:10.000-er-Bereich), lösch ich es. Darauf kommts dann auch nicht mehr
an.
Herzlichen Dank
viel gelernt :-)
Michael Prader
Nicht vergessen dass du den Zufallszahlengenerator irgendwann mal mit
echtem Zufall initialisieren musst (srand), sonst treten die Ausfälle
immer nach exakt der selben Anzahl von Vorbeifahrten auf. Am einfachsten
kannst du das machen indem du schnellen Zähler mitlaufen lässt, und wenn
der Zug über den Sensor fährt srand() mit diesem Zählerwert aufrufst.
Genaugenommen könntest du dir das rand dann auch ganz sparen, und
einfach nur den Zählerwert verwenden.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|