Implementierung von rand()

Lesezeit: 6 Minuten

Benutzer-Avatar
rlbond

Ich schreibe eingebetteten Code in C und muss die Funktion rand() verwenden. Leider wird rand() in der Bibliothek für den Controller nicht unterstützt. Ich brauche eine einfache Implementierung, die schnell ist, aber vor allem wenig Speicherplatz benötigt und relativ hochwertige Zufallszahlen erzeugt. Kennt jemand den zu verwendenden Algorithmus oder Beispielcode?

EDIT: Es ist für die Bildverarbeitung, also bedeutet “relativ hohe Qualität” eine anständige Zykluslänge und gute gleichmäßige Eigenschaften.

  • Was suchen Sie konkret? Benötigen Sie eine lange Zykluslänge? Wie groß sind die Zahlen, über die wir sprechen (16-Bit, 32-Bit, was auch immer)? Wie zufällig müssen sie sein? Beziehen Sie sich mit “Speicherplatz-Overhead” auf ROM-Beschränkungen, RAM-Beschränkungen oder beides?

    – David Thornley

    22. Juli 2009 um 18:51 Uhr

  • Wenn Sie einen SysTick oder etwas anderes haben, das verwendet werden kann, um die Zeit von der Stromversorgung bis zur aktuellen Zeit zu zählen, dann können Sie diesen Zähler als Startwert für einige der unten gezeigten Zufallsgeneratoren verwenden.

    – Avra

    2. Juli 2012 um 8:36 Uhr


  • Hier ist eine Implementierung der Mersenne-Twister in einer C++-Klasse

    – bobobobo

    3. August 2015 um 10:54 Uhr

Benutzer-Avatar
John D. Koch

Schau dir das an Sammlung von Zufallszahlengeneratoren von George Marsaglia. Er ist ein führender Experte für die Generierung von Zufallszahlen, daher würde ich zuversichtlich sein, alles zu verwenden, was er empfiehlt. Die Generatoren in dieser Liste sind winzig, einige benötigen nur ein paar unsignierte Longs als Zustand.

Die Generatoren von Marsaglia sind nach Ihren Maßstäben für lange Lebensdauer und gute gleichmäßige Verteilung definitiv “hochwertig”. Sie bestehen strenge statistische Tests, obwohl sie für die Kryptografie nicht geeignet wären.

  • Danke für den Hinweis darauf. Ich habe ein wenig recherchiert und bin fündig geworden “KISS: ein bisschen zu einfach”, von Greg Rose was (a) vor “schlechten” Seed-Werten in MWC warnt und (b) Zweifel am SHR3-Generator aufkommen lässt. Dieser Beitrag von Marsaglia aus dem Jahr 2003 gibt ein etwas anderes SHR3, das die Probleme behebt, die das frühere hatte. Ich würde gerne den Generator im KISS-Stil verwenden, solange ich “schlechte” Samen überprüfe und vermeide und sicherstelle, dass ich den besseren SHR3-Generator verwende.

    – Craig McQueen

    20. Januar 2011 um 2:06 Uhr


  • Marsaglia leistete in den 90er Jahren große Beiträge zu PRNGs, aber heute würde ich wahrscheinlich zu L’Ecuyer oder Matsumoto schauen, denke ich. Davon abgesehen, wenn das OP keine größeren Simulationen auf seinen eingebetteten Geräten durchführt, können vermutlich auch die meisten der früheren guten Generatoren verwendet werden 🙂

    – Joey

    26. Januar 2011 um 1:13 Uhr

  • @Joey: Die KISS-Generatoren von Marsaglia sind immer noch gut in L’Ecuyer’s TestU01 RNG-TestsBestehen von Tests, die sogar einige von L’Ecuyers eigenen RNGs wie z LFSR113 scheitern.

    – Craig McQueen

    20. Februar 2011 um 22:50 Uhr

Verwenden der C-Code zum LFSR113 von L’écuyer:

unsigned int lfsr113_Bits (void)
{
   static unsigned int z1 = 12345, z2 = 12345, z3 = 12345, z4 = 12345;
   unsigned int b;
   b  = ((z1 << 6) ^ z1) >> 13;
   z1 = ((z1 & 4294967294U) << 18) ^ b;
   b  = ((z2 << 2) ^ z2) >> 27; 
   z2 = ((z2 & 4294967288U) << 2) ^ b;
   b  = ((z3 << 13) ^ z3) >> 21;
   z3 = ((z3 & 4294967280U) << 7) ^ b;
   b  = ((z4 << 3) ^ z4) >> 12;
   z4 = ((z4 & 4294967168U) << 13) ^ b;
   return (z1 ^ z2 ^ z3 ^ z4);
}

Sehr hochwertig und schnell. Verwenden Sie rand() NICHT für irgendetwas. Es ist schlimmer als nutzlos.

  • Beachten Sie, dass ein 32-Bit-int angenommen wird, was für eine eingebettete Plattform möglicherweise nicht geeignet ist.

    – Tomlogik

    7. Juni 2011 um 17:49 Uhr

  • Warum genau ist das zufällig?

    – ich mich

    2. Mai 2013 um 1:52 Uhr

  • me me, es kommt darauf an, was du mit zufällig meinst. LFSR RNGs basieren auf einer wohldefinierten mathematischen Wiederholung mit bekannter Periode und guten statistischen Eigenschaften (wahrgenommene Zufälligkeit). Sofern Sie die Entropie nicht von einem physikalischen Phänomen (z. B. Leitungsrauschen) nehmen, wird jeder RNG, den Sie verwenden, ähnlich pseudozufällig sein. (Kryptografisch sichere RNGs sind komplexer, aber immer noch pseudozufällig). Der stärkere Mersenne Twister ist ein verdrehter GFSR, also ist er mit dem oben Gesagten verwandt, und der schwächere Xorshift ist ein Sonderfall von LFSR. CMWC RNGs können jedoch sowohl schneller als auch stärker sein als alle diese.

    – Mike S

    18. Juli 2013 um 22:22 Uhr

  • @me me: Es ist pseudozufällig, statische Variablen enthalten Seed-Werte. Es liefert immer die gleiche Zahlenfolge zurück.

    – k3a

    19. Juli 2015 um 13:31 Uhr

  • Wahrscheinlich ein Fehler, den Seed als statisch in die Antwort einzufügen, aber das sieht vielversprechend aus. Stellen Sie einfach sicher, dass Sie den Seed extern bereitstellen. Ich werde es versuchen. Bei 32-Bit verwendet die tatsächliche Quelle uint32_t anstelle von unsigned int, sodass dies ebenfalls kein Problem sein sollte.

    – AlexKven

    18. August 2018 um 16:33 Uhr


Hier ist ein Link zu einem ANSI C Implementierung einiger Zufallszahlengeneratoren.

Benutzer-Avatar
Craig McQueen

Ich habe eine Sammlung von Zufallszahlengeneratoren erstellt, “einfachzufällig“, die kompakt und für eingebettete Systeme geeignet sind. Die Sammlung ist verfügbar in C und Python.

Ich habe mich nach ein paar einfachen und anständigen umgesehen, die ich finden konnte, und sie in einem kleinen Paket zusammengestellt. Dazu gehören mehrere Marsaglia-Generatoren (KISS, MWC, SHR3) und einige L’Ecuyer LFSR-Generatoren.

Alle Generatoren geben eine 32-Bit-Ganzzahl ohne Vorzeichen zurück und haben typischerweise einen Status, der aus 1 bis 4 32-Bit-Ganzzahlen ohne Vorzeichen besteht.

Interessanterweise habe ich ein paar Probleme mit den Marsaglia-Generatoren gefunden und versucht, all diese Probleme zu beheben/verbessern. Diese Probleme waren:

  • Der SHR3-Generator (Bestandteil von Marsaglias KISS-Generator von 1999) war kaputt.
  • MWC Low 16 Bits haben nur ca. 229.1 Zeitraum. Also habe ich einen leicht verbesserten MWC gemacht, der den niedrigen 16 Bit eine 2 gibt59.3 Periode, die die Gesamtperiode dieses Generators ist.

Ich habe ein paar Probleme mit dem Seeding aufgedeckt und versucht, robuste Seeding- (Initialisierungs-) Verfahren zu entwickeln, damit sie nicht kaputt gehen, wenn Sie ihnen einen “schlechten” Seed-Wert geben.

Benutzer-Avatar
Norman Ramsey

Ich empfehle die wissenschaftliche Arbeit Zwei schnelle Implementierungen des minimalen Standard-Zufallszahlengenerators von David Carta. Sie können kostenlose PDF-Dateien über Google finden. Lesenswert ist auch die Originalarbeit zum Minimal Standard Random Number Generator.

Der Code von Carta liefert schnelle, qualitativ hochwertige Zufallszahlen auf 32-Bit-Rechnern. Für eine gründlichere Bewertung siehe das Papier.

Benutzer-Avatar
Yongji Chen

Mersenne-Twister

Etwas aus Wikipedia:

  • Es wurde für eine Periode von 2 entwickelt19937 − 1 (die Ersteller des Algorithmus haben diese Eigenschaft bewiesen). In der Praxis gibt es wenig Grund, einen größeren Zeitraum zu verwenden, da die meisten Anwendungen 2 nicht benötigen19937 einzigartige Kombinationen (219937 ist ungefähr 4,3 × 106001; Dies ist viele Größenordnungen größer als die geschätzte Anzahl von Teilchen im beobachtbaren Universum, die 10 beträgt80).
  • Es hat eine sehr hohe Ordnung der dimensionalen Gleichverteilung (siehe linearer Kongruenzgenerator). Dies impliziert, dass es eine vernachlässigbare serielle Korrelation zwischen aufeinanderfolgenden Werten in der Ausgangssequenz gibt.
  • Es besteht zahlreiche Tests auf statistische Zufälligkeit, einschließlich der Diehard-Tests. Es besteht die meisten, aber nicht alle der noch strengeren TestU01 Crush Randomness Tests.

  • Quellcode für viele Sprachen unter dem Link verfügbar.

Benutzer-Avatar
Daniel Ohrwicker

Ich würde eine aus der GNU C-Bibliothek nehmen, die Quelle kann online durchsucht werden.

http://qa.coreboot.org/docs/libpayload/rand_8c-source.html

Aber wenn Sie irgendwelche Bedenken hinsichtlich der Qualität der Zufallszahlen haben, sollten Sie sich wahrscheinlich sorgfältiger geschriebene mathematische Bibliotheken ansehen. Es ist ein großes Thema und der Standard rand Implementierungen werden von Experten nicht sehr geschätzt.

Hier noch eine Möglichkeit: http://www.boost.org/doc/libs/1_39_0/libs/random/index.html

(Wenn Sie feststellen, dass Sie zu viele Optionen haben, können Sie jederzeit eine zufällig auswählen.)

  • Das rand.c Quellcode-Link scheint defekt zu sein. Probieren Sie das Git-Repo für rand.c und random.c

    – Craig McQueen

    14. Februar 2011 um 1:05 Uhr

  • Beachten Sie, dass der Code unter der GPL oder LGPL stehen wird. Kennen Sie immer die Lizenz Ihrer Quellen.

    – davenpcj

    17. April 2013 um 23:56 Uhr

1284150cookie-checkImplementierung von rand()

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy