Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Random Periodicity Test Code for arduino (compiled in Arduino IDE)
/*
* Test sketch based on rand-period-test.c by @unprovable
* His sketch shown an anomaly with Arduino's PRNG, in which the LCG period seems to be unreliable.
* Also the function seems to be quite slow; iterating over the stream until we get back to the beginning
* takes 199340888ms (55.3724689 hours). It takes 1.5 minutes (approx) to generate 1M numbers.
* So I decided to repeat the test with a textbook implementation of a standard LCG to see if we can get a
* reliable generator with a stable period (and hopefully faster runtime) under the same conditions.
* In my test, this script takes ~47 seconds each 1M numbers, and 103345725 ms (28.707146 hours) in total,
* with a period that matches the theoretical expected value of 7FFFFFFF, so if you are going to do random
* with an arduino, even a regular standard LCG implementation is way better than what you get out of the
* box.
* NOTE: Tests performed on an Arduino Nano (Atmega328p processor) @ 16Mhz.
*/
long rand_i, rand_j, rand_k;
unsigned long i = 0, j = 0, k = 0;
long startTime;
long lastTime;
long now;
unsigned long lcg_seed = 0x50000L; // Could be any value
unsigned long rand2(){
lcg_seed = (lcg_seed * 1103515245L + 12345L) % 2147483648L;
return lcg_seed;
}
void setup() {
// put your setup code here, to run once:
rand_i = rand2();
rand_j = rand2();
rand_k = rand2();
Serial.begin(57600);
while (!Serial) {}
Serial.print("starting num rand_i: "); Serial.println(rand_i, HEX);
Serial.print("starting num rand_j: "); Serial.println(rand_j, HEX);
Serial.print("starting num rand_k: "); Serial.println(rand_k, HEX);
pinMode(LED_BUILTIN, OUTPUT);
Serial.print("using rand_k = ");Serial.println(rand_k);
startTime = millis();
lastTime = startTime;
}
void loop() {
// put your main code here, to run repeatedly:
if ((i % 1000000) == 0) {
now = millis();
Serial.print("Up to ");
Serial.print(i);
Serial.print(" iterations in ");
Serial.print((long)(now - lastTime), DEC);
Serial.println(" ms");
lastTime = now;
}
if (rand2() == rand_k) {
now = millis();
Serial.print("MATCH!! We got a match on "); Serial.print(rand_k); Serial.print(" in "); Serial.print(i, HEX); Serial.println(" operations.");
//i = 0;
while(true){
Serial.print("MATCH!! We got a match on "); Serial.print(rand_k); Serial.print(" in "); Serial.print(i, HEX); Serial.println(" operations.");
Serial.print("-- It took ");
Serial.print((long)(now - startTime), DEC);
Serial.println(" ms");
digitalWrite(LED_BUILTIN, HIGH);
delay(50000);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}; // stop the duino so we can see what the magic number is :-P Keep printing in case the serial port goes to sleep...
}
i++;
}
Owner

battlecoder commented Nov 24, 2017

If you are wondering how this code compares to unprovable's sketch but you don't want to run a diff: This sketch is exactly the same, but it uses a standard LCG (implemented in rand2()) instead of Arduino's random().

It also has a global time counter to know how much time it takes to run this whole thing, which is something I also added to my local copy of his sketch when I ran the test on my Arduino. That's how I know how much time it took, and was able to compare.

If you run mine and unprovable's sketch on an Arduino other than a Nano @ 16Mhz, let me know! I'd be quite interesting in knowing what the performance is like on other Arduinos, with different processors or clock speeds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment