Ok, auch die Variante mit der Multiplikation hat da naturgemäß gewisse Defizite bei der Gleichverteilung. Immerhin sind die häufigen und die weniger häufigen Zahlen einigermaßen gleichmäßig über den Wertebereich verteilt, wogegen bei der Modulo-Variante die kleineren Zahlen häufiger vorkommen (ob eines davon besser ist, mag jeder selbst beurteilen).
Markus
Didn't find your answer? Ask the community — no account required.
R
Rafael Deliano
Selber implementieren: etwas mehr Zeitaufwand in der Codierungsphase, deutlich weniger Frust in der Testphase.
Muß man sich klar werden was man will: die üblichen derartigen Grundfunktionen liefern Gleichverteilung nicht Gaußverteilung. Und meist auch ohne den Wert 0. D.h. will man eine "natürliche" Gaußkurve mit Mittelwert 3sec ?
Für Modellbau zur Simulation "Feuerschein, brennendes Haus" mit LEDs scheint typisch LFSR d.h. Gleichverteilung gereicht zu haben.
Zur Implementierungen der Grundfunktion mit Gleichverteilung auf Controller eignet sich: a) lineare Kongruenz LCG: bessere Verteilung, benötigt aber Multiplikation Da 8 bit Controller bereits 8x8->16Bit Befehl haben heute oft von Rechenzeit akzeptabel. b) LFSR Linear Feedback Shift Register: minimaler Aufand, maue Qualität. c) noch mieser: 256 Byte Tabelle die man z.B. während Compilierung mit LFSR füllt. Das hat bei mir schonmal voll gereicht einem PWM-getakteten Schrittmotor das unangenehme Pfeifen abzugewöhnen.
Die Umwandlung von Gleichverteilung auf Gauß auf 8 Bit Controller typisch LCG und Mittelwert über 12 Samples. Auf Seite 7/8 von Heft 2 / 2007 der FORTH e.V. kurzer Artikel:
formatting link
Man kann sich andere Varianten ausdenken: ( unfertig )
formatting link
Die timing Angaben beziehen sich auf 68HC908 der im Befehlssatz ähnlich AVR ist, aber langsamer.
Ein ungelöstes und auch schwer lösbares Problem ist "zufälliger" Startwert SEED für LCG und LFSR. Minimal sollte man nach Reset ein Bit setzen damit der Wert wenigstens nicht 0 ist.
MfG JRD
M
M.Dinsch
Am Thu, 15 Aug 2013 09:39:33 +0200, meinte Rafael Deliano :
Naja .... ich wollte eigentlich nicht auch noch in die Untiefen (bzw. undendlichen Tiefen) der Erzeugung einer Zufallszahl mittels uC eintauchen ...
Ich bin nicht sicher, Dich richig zu verstehen. Ungebildet wie ich in dieser Hinsicht bin bedeutet für mich "zufällig" eben, daß auf Dauer alle Werte gleich häufig auftreten. Eine Häufigkeitsverteilung nach der Gaußschen Kurve ist aber doch gerade das Gegenteil, nämlich eine Häufung der Werte/Ergebnisse um den Mittelwert von 3 (bei einem Wertebereich von 0 bis 6). Wobei das "gleich häufig" hier nicht wirklich wörtlich zu nehmen ist, ich möchte nur keine "Klumpenbildung" um eine bestimmte Zeitdauer.
Meine Anmerkung bezog sich auf die konkrete Anwendung der rnd()-Funktion: Wenn es vom Ergebnis her egal ist, ob ich für rnd() einen Wertebereich bis 40 vorgebe oder z.B. als Wertebereich 40000 nehme und dann auf (in diesem Beispiel) 40 Werte für die Verzögerung herunterrechne, dann kann ich es so belassen wie es ist.
Das habe ich jetzt nicht verstanden - aber auch nicht, was ich mit der Vorgabe eines SEED-Werts bewirken kann (die BASCOM-Hilfe ist für mich unverständlich).
R
Rafael Deliano
formatting link
dürfte ein LCG sein:
formatting link
Die Funktion hat eine 16 Bit Variable SEED die man laden muß/sollte, bevor man aus dem Generator Werte entnimmt. BASACOM empfiehlt einen 16 Bit Timerwert als Startwert reinzukopieren. Das ist jedenfalls besser als eine Konstante und durchaus praktikabel.
Hängt letztlich von der Anwendung ab was man will: die Gaußverteilung ist die "natürliche" Verteilung für die meisten physikalischen Vorgänge a la analoges Rauschen. BASCOM wird absehbar Gleichverteilung und nicht Gauß liefern.
MfG JRD
P
Peter Schneider
M.Dinsch schrieb:
[rnd-Funktion]
Die rnd-Funktion liefert keine wirklich zufälligen Zahlen, sondern eine deterministische, sich zyklisch wiederholende Pseudo-Zufallszahlenfolge. Die Startposition innerhalb dieser zyklischen Folge ist durch den SEED-Wert beeinflussbar.
Falls es für deine Anwendung akzeptabel ist, dass jedesmal nach dem Einschalten die gleichen 'Zufallszahlen' generiert werden, musst du nichts unternehmen, dann ist rnd() gut genug.
Ist das jedoch unerwünscht, musst du für sogenannte 'Entropie' sorgen, und damit den SEED initialisieren, oder dafür sorgen, dass die Position in deiner Zufallszahlenfolge über das Ausschalten hinaus gespeichert wird.
Entropie kann man durch Ereignisse, die eben nicht jedesmal nach dem Einschalten auf die gleiche Art ablaufen, gewinnen:
- Zeitpunkt von Tastendrücken des Benutzers
- die untersten Bits von digitalisierten Analogsignalen (Rauschen)
- Zeitpunkt des Einschaltens, falls eine Echtzeituhr verfügbar ist
Alternativ könntest du die jeweils zuletzt generierte Zufallszahl im nichtflüchtigen Speicher (EEPROM) des Controllers speichern und als Startwert fürs nächste Einschalten verwenden. Dabei muss man allerdings auf die Lebensdauer der EEPROM-Zellen achten, die lassen sich nur begrenzt oft (z.B. 100000 mal) programmieren. Man kann den Wert aber auf mehrere EEPROM-Zellen verteilen, so dass die Gesamtlebensdauer dann wieder passt.
P.
M
M.Dinsch
Am Sat, 17 Aug 2013 14:58:00 +0200, meinte "Peter Schneider" :
Ersteres war mir klar, jetzt verstehe ich auch SEED. Danke.
Ja, das spielt nicht die geringste Rolle.
Wie geschrieben bin ich unsicher hinsichtlich der onkreten Anwendung der rnd()-Funktion: Wenn es vom Ergebnis her egal ist, ob ich für rnd() einen Wertebereich bis 40 vorgebe oder z.B. als Wertebereich
40000 nehme und dann auf (in diesem Beispiel) 40 Werte für die Verzögerung herunterrechne, dann kann ich es so belassen wie es ist.
P
Peter Schneider
M.Dinsch schrieb:
Solange du nicht weißt, wie die rnd-Funktion implementiert ist, kannst du da nicht sicher sein.
Das an anderer Stelle im Thread genannte Beispiel in der Arduino-Programmierumgebung ist da z.B. suboptimal implementiert.
Wenn du dir dort Zahlen modulo 40000 wünschst, ergibt sich eine stark verzerrte Verteilung, da der Zufallszahlengenerator (RNG) Zahlen im Bereich von 0 bis 65535 liefert und der zurückgelieferte Wert modulo 40000 berechnet wird.
RNG random()-Wert
0...39999 0..39999
40000..65535 0..25535
Somit ergibt sich trotz Gleichverteilung des RNG eine doppelt so hohe Wahrscheinlichkeit für die 20000 wie für die 30000. Wenn du das Ergebnis noch durch 1000 teilst, wird das nicht besser, die 20 kommt doppelt so oft wie die 10 vor.
Die Verzerrung ist bei Berechnung modulo 40 nicht so schlimm, und bei modulo-Werten, die Potenzen von 2 sind (Teiler von 65536), bleibt es bei einer Gleichverteilung.
Wie das bei der Bascom-Library aussieht, bleibt vermutlich das Geheimnis des Herstellers, bis du den Disassembler ansetzt oder die Gleichverteilung durch ein Testprogramm überprüfst.
P.
P
Peter Thoms
Am 13.08.2013 14:07, schrieb Peter Schneider:
Hallo,
bei so wenig Programmcode kann auch gleich mit C begonnen werden. Das schluckt auch problemlos Assembler.
- codeblocks oder
- devc++
mit
formatting link
Peter
M
M.Dinsch
Am Sat, 17 Aug 2013 17:10:51 +0200, meinte "Peter Schneider" :
...
So etwas meinte ich.
Wäre es dann nicht sinnvoller, sicherheitshalber den vollen Bereich von 65535 zu wählen und das Ergebnis mit einer zehnfachen Shift-Operation in den brauchbaren Bereich bis ungefähr 60 zu dividieren?
P
Peter Schneider
M.Dinsch schrieb:
Ja, falls 0..65535 der 'natürliche' Bereich der Bascom-Funktion ist. Die von Rafael verlinkte Doku sagt: "returns an Integer/Word" und "Each new call to Rnd() will give a new positive random number."
Was das genau in Basic-Speak bedeutet, weiß ich nicht.
P.
W
wernertrp
Am Dienstag, 13. August 2013 13:12:52 UTC+2 schrieb M. Dinsch:
l,
Wenn man sich nicht in die Hardware eines MPs einarbeiten will, so nimmt ma n eine kleine Basic Platine von:
formatting link
S
Sieghard Schicktanz
Hallo Peter,
Du schriebst am Sat, 17 Aug 2013 17:10:51 +0200:
^^ Meintest Du hier nicht eher 30?
--
(Weitergabe von Adressdaten, Telefonnummern u.ä. ohne Zustimmung
nicht gestattet, ebenso Zusendung von Werbung oder ähnlichem)
-----------------------------------------------------------
Mit freundlichen Grüßen, S. Schicktanz
-----------------------------------------------------------
S
Sieghard Schicktanz
Hallo M.Dinsch,
Du schriebst am Sat, 17 Aug 2013 11:01:21 +0200:
Bit
Es gibt Algorithmen, die bei 0 eine recht wenig zufällige Folge liefer n, nämlich nach dem Motto "einmal 0, immer 0". Das nennt man einen "Fixpu nkt" des Algorithmus - einmal erreicht, wird er nie wieder verlassen. Allerdings ist er insofern wenig kritisch, als er nur von einem einzigen Startwert aus erreicht werden kann (er ist disjunkt zu dem anderen, üblichen Wertebereich), nämlich vom Wert 0 aus. Deshalb ist es n ützlich, den Startwert so zu initialisieren, daß er mit Sicherheit nicht 0 sein kann.
--
(Weitergabe von Adressdaten, Telefonnummern u.ä. ohne Zustimmung
nicht gestattet, ebenso Zusendung von Werbung oder ähnlichem)
-----------------------------------------------------------
Mit freundlichen Grüßen, S. Schicktanz
-----------------------------------------------------------
P
Peter Schneider
Sieghard Schicktanz schrieb:
Ja, gut aufgepasst, meinte ich.
P.
H
Heiko Nocon
Solche Algorithmen sind allerdings völlig indiskutabel. Nicht nur wegen des Fixpunkt an sich, sondern umgekehrt auch, weil eben dieser Fixpunkt ja auch nicht Teil der "normalen" Peudozufallsfolge sein kann.
Welcher Idiot verwendet _heute_ noch so einen Algorithmus?
M
Michael Eggert
Moin!
Alternativ addiert man den neuen Zufallswert zum alten Modulowert und bildet erst dann den neuen Modulo. So sollte es wieder gleichverteilt sein.
Gruß, Michael.
B
Bernd Laengerich
Am 17.08.2013 12:05, schrieb Rafael Deliano:
Hilft hier vermutlich nicht wirklich. Das Programm startet mit dem Einschalten der Betriebsspannung, d.h. der Timerwert dürfte immer gleich sein.
Bernd
P
Peter Heitzer
Das gilt i.d.R. nur für LFSR. Dort ist entweder lauter Nullbits oder lauter Einsbits verboten.
Dipl.-Inform(FH) Peter Heitzer, peter.heitzer@rz.uni-regensburg.de
HTML mails will be forwarded to /dev/null.
R
Rafael Deliano
Bezogen auf 16 Bit und die übliche m-Sequenz: es werden alle Werte ausser 0000 erzeugt. Insofern würde man SEED auch FFFF starten können.
MfG JRD
R
Rafael Deliano
Gerade mal den von mir meist verwendeten LCG in FORTH nochmal ausprobiert: