Repetition of pseudorandom Random() sequence

As I understand it, the Arduino's random number generator produces a sequence of pseudorandom numbers that eventually repeats. Giving it a new seed with RandomSeed() doesn't change to a different number sequence, it just jumps to a different location within the same sequence.

My questions are:

How long is this sequence; ie how many numbers can be produced before they start repeating? And is an 8-bit value in RandomSeed() enough to make sure repeated sequences of 'random' numbers are vanishingly unlikely?

Yup. Yup. 2^31-1. Doubt it. Using an eight bit seed will make the quality of the sequence significantly lower. You are far better served saving / restoring the seed so the generator can run through the full cycle.

More information...

Thanks for your advice, that's helpful. How does one access the random seed in Arduino code?

Call random() to read the next value in the sequence which is the new seed value.

Call srandom(value) to set the seed.

This may help...
http://forum.arduino.cc/index.php?topic=66206.0

note that srandom() still has only a 16 bit seed - randomSeed should have unsigned long as parameter [imported] · Issue #575 · arduino/Arduino · GitHub -

srandom is fine. randomSeed is the problem.

http://forum.arduino.cc/index.php?topic=66206.msg505310#msg505310

:wink:

The code for random() is alas in stdlib, so no source that I can find, however the
disassembly suggests its just a linear congruence generator, which are usually maximal
sequences over 2^n-1 (but poor quality randomness).

[ quick bit of research suggests from the integer constants in the code that its this
function: http://open-last-chaos.googlecode.com/svn/trunk/Connector/src/Random.cpp

In fact here's the original paper about all this:

]

Oh yes, never use such a pseudo random generator for cryptography, they are not
in any way secure.

See this thread for a discussion about alternatives:

http://forum.arduino.cc/index.php?topic=263849

Example random generator:

/* Implementation of a 32-bit KISS generator which uses no multiply instructions */
static unsigned long x=123456789,y=234567891,z=345678912,w=456789123,c=0;
unsigned long JKISS32()
{
  long t;
  y ^= y << 5; 
  y ^= y >> 7; 
  y ^= y << 22;
  t = z + w + c; 
  z = w; 
  c = t < 0; 
  w = t & 2147483647;
  x += 1411392427;
  return x + y + w;
}

Example seeder:

void tc_RandomSeed_JKISS32( unsigned long newseed )
{
  if ( newseed != 0 )
  {
    x = 123456789;
    y = newseed;
    z = 345678912;
    w = 456789123;
    c = 0;
  }
}

The AVR Libc source code for random is available here...
http://svn.savannah.nongnu.org/viewvc/avr-libc-1_8_1-release/libc/stdlib/rand.c?root=avr-libc&view=markup
http://svn.savannah.nongnu.org/viewvc/avr-libc-1_8_1-release/libc/stdlib/random.c?root=avr-libc&view=markup

/* Implementation of a 32-bit KISS generator which uses no multiply instructions */

Does it pass statistical testsuites?

What is the cycle length?

Are there any short cycles?

Are there bad seed values?

See this: http://zygomorphic.com/arduino-tiny/?p=39

From the PDF linked to on that page ( http://www.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf ):

If your language only handles 32-bit integers or even has difficulties with unsigned integers (e.g.
Fortran), or you just want a faster generator that avoids multiplication, Marsaglia has proposed
using an add-with-carry generator rather than the superior multiply-with-carry. Although I prefer to
use the full multiplicative KISS, I do really like this 32-bit generator because it is the simplest and
fastest RNG that I know of which passes all of the Dieharder tests and the BigCrunch tests in
TestU01. The period is ?2 121 = 2.6 x 10 36 .

I made this test case on Ubuntu (using unsigned int because that is what gives a 32-bit int on this processor):

#include <stdio.h>
/* Implementation of a 32-bit KISS generator which uses no multiply instructions */
static unsigned int x=123456789,y=234567891,z=345678912,w=456789123,c=0;
unsigned int JKISS32()
{
  int t;
  y ^= y << 5;
  y ^= y >> 7;
  y ^= y << 22;
  t = z + w + c;
  z = w;
  c = t < 0;
  w = t & 2147483647;
  x += 1411392427;
  return x + y + w;
}

int main ()
{
while (1)
  {
  unsigned int r = JKISS32 ();
  fwrite (&r, 4, 1, stdout);
  }
return 0;
}

I tested like this:

./kiss32 | dieharder -a -g 200

Resuts:

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  5.80e+07  |4078820604|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.03307654|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.88004083|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.41930350|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.73296855|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.48591461|  PASSED  
        diehard_opso|   0|   2097152|     100|0.90387282|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.28068373|  PASSED  
         diehard_dna|   0|   2097152|     100|0.83973715|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.58849849|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.26356325|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.37131003|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.70442965|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.34122464|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.08921174|  PASSED  
        diehard_sums|   0|       100|     100|0.08147020|  PASSED  
        diehard_runs|   0|    100000|     100|0.08217975|  PASSED  
        diehard_runs|   0|    100000|     100|0.55030731|  PASSED  
       diehard_craps|   0|    200000|     100|0.36079634|  PASSED  
       diehard_craps|   0|    200000|     100|0.76707625|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.79448111|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.14836390|  PASSED  
         sts_monobit|   1|    100000|     100|0.98497349|  PASSED  
            sts_runs|   2|    100000|     100|0.86910149|  PASSED  
          sts_serial|   1|    100000|     100|0.11369182|  PASSED  
          sts_serial|   2|    100000|     100|0.89986352|  PASSED  
          sts_serial|   3|    100000|     100|0.98999508|  PASSED  
          sts_serial|   3|    100000|     100|0.29880385|  PASSED  
          sts_serial|   4|    100000|     100|0.84496312|  PASSED  
          sts_serial|   4|    100000|     100|0.51021114|  PASSED  
          sts_serial|   5|    100000|     100|0.27616427|  PASSED  
          sts_serial|   5|    100000|     100|0.12839023|  PASSED  
          sts_serial|   6|    100000|     100|0.16757307|  PASSED  
          sts_serial|   6|    100000|     100|0.84914965|  PASSED  
          sts_serial|   7|    100000|     100|0.79000677|  PASSED  
          sts_serial|   7|    100000|     100|0.34011136|  PASSED  
          sts_serial|   8|    100000|     100|0.59161490|  PASSED  
          sts_serial|   8|    100000|     100|0.19817940|  PASSED  
          sts_serial|   9|    100000|     100|0.19569430|  PASSED  
          sts_serial|   9|    100000|     100|0.06356432|  PASSED  
          sts_serial|  10|    100000|     100|0.35587449|  PASSED  
          sts_serial|  10|    100000|     100|0.43895831|  PASSED  
          sts_serial|  11|    100000|     100|0.38808666|  PASSED  
          sts_serial|  11|    100000|     100|0.02427212|  PASSED  
          sts_serial|  12|    100000|     100|0.13959434|  PASSED  
          sts_serial|  12|    100000|     100|0.87174304|  PASSED  
          sts_serial|  13|    100000|     100|0.44789999|  PASSED  
          sts_serial|  13|    100000|     100|0.90732514|  PASSED  
          sts_serial|  14|    100000|     100|0.82787900|  PASSED  
          sts_serial|  14|    100000|     100|0.56555426|  PASSED  
          sts_serial|  15|    100000|     100|0.89826206|  PASSED  
          sts_serial|  15|    100000|     100|0.56477897|  PASSED  
          sts_serial|  16|    100000|     100|0.48666295|  PASSED  
          sts_serial|  16|    100000|     100|0.47952162|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.47766161|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.72380052|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.25048127|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.10199211|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.71996662|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.86952107|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.59202528|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.81732167|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.44798263|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.57945709|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.16639436|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.43479261|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.00133214|   WEAK   
rgb_minimum_distance|   3|     10000|    1000|0.74242368|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.35832274|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.93948454|  PASSED  
    rgb_permutations|   2|    100000|     100|0.19907388|  PASSED  
    rgb_permutations|   3|    100000|     100|0.54692330|  PASSED  
    rgb_permutations|   4|    100000|     100|0.96139064|  PASSED  
    rgb_permutations|   5|    100000|     100|0.39983634|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.30933462|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.55797078|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.90683136|  PASSED  
      rgb_lagged_sum|   3|   1000000|     100|0.40325839|  PASSED  
      rgb_lagged_sum|   4|   1000000|     100|0.01898008|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.28246826|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.97510313|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.79719067|  PASSED  

... (some tests omitted due to message length, all passed) ...

      rgb_lagged_sum|  25|   1000000|     100|0.96320195|  PASSED  
      rgb_lagged_sum|  26|   1000000|     100|0.25663265|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.77025868|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.64147414|  PASSED  
      rgb_lagged_sum|  29|   1000000|     100|0.09946415|  PASSED  
      rgb_lagged_sum|  30|   1000000|     100|0.48749316|  PASSED  
      rgb_lagged_sum|  31|   1000000|     100|0.56088593|  PASSED  
      rgb_lagged_sum|  32|   1000000|     100|0.46998944|  PASSED  
     rgb_kstest_test|   0|     10000|    1000|0.24784991|  PASSED  
     dab_bytedistrib|   0|  51200000|       1|0.11155315|  PASSED  
             dab_dct| 256|     50000|       1|0.19169188|  PASSED  
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.62717317|  PASSED  
        dab_filltree|  32|  15000000|       1|0.06917141|  PASSED  
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.26124064|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.01206766|  PASSED  
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.80531060|  PASSED

MarkT:
Are there bad seed values?

y = 0 is probably a bad choice. :wink:

Bear in mind the seed function above is incomplete. What I remember is that all five variables are the seed and should be initialized. I wrote the function above to make the generator more compatible with the existing Arduino API.

Compare to the Marsenne Twiser output:

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
   mt19937_1998|  1.96e+08  |4002501982|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.61671435|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.78296503|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.72498389|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.99696732|   WEAK   
   diehard_bitstream|   0|   2097152|     100|0.14592345|  PASSED  
        diehard_opso|   0|   2097152|     100|0.73904667|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.16070148|  PASSED  
         diehard_dna|   0|   2097152|     100|0.40260265|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.78313093|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.55209698|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.68281092|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.59812934|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.34017222|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.25804905|  PASSED  
        diehard_sums|   0|       100|     100|0.13664518|  PASSED  
        diehard_runs|   0|    100000|     100|0.26409703|  PASSED  
        diehard_runs|   0|    100000|     100|0.20515133|  PASSED  
       diehard_craps|   0|    200000|     100|0.35732336|  PASSED  
       diehard_craps|   0|    200000|     100|0.73578965|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.50002373|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.01039527|  PASSED  
         sts_monobit|   1|    100000|     100|0.98469816|  PASSED  
            sts_runs|   2|    100000|     100|0.01522842|  PASSED  
          sts_serial|   1|    100000|     100|0.21567355|  PASSED  
          sts_serial|   2|    100000|     100|0.88353218|  PASSED  
          sts_serial|   3|    100000|     100|0.95415130|  PASSED  
          sts_serial|   3|    100000|     100|0.83095013|  PASSED  
          sts_serial|   4|    100000|     100|0.15906879|  PASSED  
          sts_serial|   4|    100000|     100|0.23125226|  PASSED  
          sts_serial|   5|    100000|     100|0.30323405|  PASSED  
          sts_serial|   5|    100000|     100|0.40194244|  PASSED  
          sts_serial|   6|    100000|     100|0.79762014|  PASSED  
          sts_serial|   6|    100000|     100|0.94139973|  PASSED  
          sts_serial|   7|    100000|     100|0.45821083|  PASSED  
          sts_serial|   7|    100000|     100|0.13571559|  PASSED  
          sts_serial|   8|    100000|     100|0.84743195|  PASSED  
          sts_serial|   8|    100000|     100|0.89917131|  PASSED  
          sts_serial|   9|    100000|     100|0.43459363|  PASSED  
          sts_serial|   9|    100000|     100|0.23222254|  PASSED  
          sts_serial|  10|    100000|     100|0.62195134|  PASSED  
          sts_serial|  10|    100000|     100|0.44435275|  PASSED  
          sts_serial|  11|    100000|     100|0.71449679|  PASSED  
          sts_serial|  11|    100000|     100|0.57682450|  PASSED  
          sts_serial|  12|    100000|     100|0.94901857|  PASSED  
          sts_serial|  12|    100000|     100|0.63005802|  PASSED  
          sts_serial|  13|    100000|     100|0.62593073|  PASSED  
          sts_serial|  13|    100000|     100|0.46734226|  PASSED  
          sts_serial|  14|    100000|     100|0.95773048|  PASSED  
          sts_serial|  14|    100000|     100|0.25408097|  PASSED  
          sts_serial|  15|    100000|     100|0.62858344|  PASSED  
          sts_serial|  15|    100000|     100|0.33350146|  PASSED  
          sts_serial|  16|    100000|     100|0.89530940|  PASSED  
          sts_serial|  16|    100000|     100|0.07069205|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.32359881|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.87421156|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.90785453|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.85770089|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.62290857|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.92161877|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.73153391|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.56943049|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.47165819|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.56769214|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.98817277|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.60181406|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.90157061|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.46061896|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.82815090|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.07133976|  PASSED  
    rgb_permutations|   2|    100000|     100|0.32011924|  PASSED  
    rgb_permutations|   3|    100000|     100|0.29167639|  PASSED  
    rgb_permutations|   4|    100000|     100|0.79678442|  PASSED  
    rgb_permutations|   5|    100000|     100|0.27139662|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.24347131|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.69879574|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.99516796|   WEAK   
      rgb_lagged_sum|   3|   1000000|     100|0.91469411|  PASSED  
      rgb_lagged_sum|   4|   1000000|     100|0.09091343|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.90032653|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.32236123|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.17326903|  PASSED  
      rgb_lagged_sum|   8|   1000000|     100|0.40710864|  PASSED  
      rgb_lagged_sum|   9|   1000000|     100|0.39178375|  PASSED  
      rgb_lagged_sum|  10|   1000000|     100|0.14601055|  PASSED  
      rgb_lagged_sum|  11|   1000000|     100|0.57822219|  PASSED  
      rgb_lagged_sum|  12|   1000000|     100|0.99709220|   WEAK   
      rgb_lagged_sum|  13|   1000000|     100|0.66993278|  PASSED  
      rgb_lagged_sum|  14|   1000000|     100|0.32737613|  PASSED  
      rgb_lagged_sum|  15|   1000000|     100|0.62091065|  PASSED  
      rgb_lagged_sum|  16|   1000000|     100|0.91199984|  PASSED  
      rgb_lagged_sum|  17|   1000000|     100|0.09579321|  PASSED  
      rgb_lagged_sum|  18|   1000000|     100|0.88220512|  PASSED  
      rgb_lagged_sum|  19|   1000000|     100|0.62465972|  PASSED  
      rgb_lagged_sum|  20|   1000000|     100|0.99458705|  PASSED  
      rgb_lagged_sum|  21|   1000000|     100|0.41738784|  PASSED  
      rgb_lagged_sum|  22|   1000000|     100|0.08671640|  PASSED  
      rgb_lagged_sum|  23|   1000000|     100|0.46819785|  PASSED  
      rgb_lagged_sum|  24|   1000000|     100|0.79054363|  PASSED  
      rgb_lagged_sum|  25|   1000000|     100|0.90831002|  PASSED  
      rgb_lagged_sum|  26|   1000000|     100|0.84671412|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.87013638|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.40800397|  PASSED  
      rgb_lagged_sum|  29|   1000000|     100|0.69498499|  PASSED  
      rgb_lagged_sum|  30|   1000000|     100|0.38559746|  PASSED  
      rgb_lagged_sum|  31|   1000000|     100|0.50844188|  PASSED  
      rgb_lagged_sum|  32|   1000000|     100|0.78982750|  PASSED  
     rgb_kstest_test|   0|     10000|    1000|0.36267308|  PASSED  
     dab_bytedistrib|   0|  51200000|       1|0.17295188|  PASSED  
             dab_dct| 256|     50000|       1|0.47664115|  PASSED  
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.11714740|  PASSED  
        dab_filltree|  32|  15000000|       1|0.98918917|  PASSED  
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.54267305|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.70933128|  PASSED  
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.76447055|  PASSED

In regards to dieharder and other statistical tests: sometimes p happens. An occasional "weak" is normal. A rare "fail" is even normal.

In other words, they are both very good generators.

Just for fun I tested with y = 0; and got this (first few tests):

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  5.77e+07  |3379353257|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.30075036|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.00000000|  FAILED  
  diehard_rank_32x32|   0|     40000|     100|0.79829420|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.00000000|  FAILED  
   diehard_bitstream|   0|   2097152|     100|0.95327567|  PASSED  
        diehard_opso|   0|   2097152|     100|0.04170381|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.00000000|  FAILED  
         diehard_dna|   0|   2097152|     100|0.00000000|  FAILED  
diehard_count_1s_str|   0|    256000|     100|0.00000013|  FAILED  
diehard_count_1s_byt|   0|    256000|     100|0.00000000|  FAILED  
 diehard_parking_lot|   0|     12000|     100|0.00000000|  FAILED  
    diehard_2dsphere|   2|      8000|     100|0.08659795|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.00000000|  FAILED  
     diehard_squeeze|   0|    100000|     100|0.00000000|  FAILED  
        diehard_sums|   0|       100|     100|0.00000000|  FAILED  
        diehard_runs|   0|    100000|     100|0.00000000|  FAILED  
        diehard_runs|   0|    100000|     100|0.00000000|  FAILED  
       diehard_craps|   0|    200000|     100|0.00000000|  FAILED  
       diehard_craps|   0|    200000|     100|0.00000000|  FAILED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.00000000|  FAILED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.86801918|  PASSED  
         sts_monobit|   1|    100000|     100|0.85904846|  PASSED

But with y = 1, I got this:

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  5.91e+07  |3198615326|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.76352514|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.80969575|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.98443640|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.79245553|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.15452550|  PASSED  
        diehard_opso|   0|   2097152|     100|0.51475611|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.48991786|  PASSED  
         diehard_dna|   0|   2097152|     100|0.35247335|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.45942448|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.78867631|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.39654442|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.97480966|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.99392773|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.11012652|  PASSED  
        diehard_sums|   0|       100|     100|0.59669025|  PASSED  
        diehard_runs|   0|    100000|     100|0.96140155|  PASSED  
        diehard_runs|   0|    100000|     100|0.30936843|  PASSED  
       diehard_craps|   0|    200000|     100|0.62925693|  PASSED  
       diehard_craps|   0|    200000|     100|0.91845410|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.95353259|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.73556725|  PASSED  
         sts_monobit|   1|    100000|     100|0.87830484|  PASSED

Yes, if they always passed they would be too predicatable, eh?

Pseudorandom number generators are perfectly predictable so predictability is not the issue.

This is the issue...

I'll use flipping a coin as an example. If I flip a coin one million times and get heads one million times, is the coin fair? It turns out, we can't tell. The chances of one million heads from one million flips is extremely low. But the chances are not zero. That's the important part. The chances are not zero. With truly random numbers, every so often something freaky happens. When a sequence fails a single statistical test, we cannot tell if the failure is because the sequence is low quality or because something freaky happened. "Sometimes p happens" means that even truly random numbers occasionally fail a p-test.

Note: In general the above is true. Some of the tests are designed to test for specific kinds of PRNG failures. I suspect searching for RANDU will uncover a good example. I believe the Libc random function always fails diehard_rank_32x32 and diehard_rank_6x8.

I was making a bit of a joke. Say we tossed a coin 100 times and always, every time, got 50 heads and 50 tails, there would be something wrong. Why? Because after 99 tosses we know what the final one must be. Therefore it's not random, even if the results inbetween "look random".

Interestingly, I believe (some) games actually filter the random number output to make it "look random".

Say, for example, after doing a number of dungeons, at the end you and I "roll" for the single piece of good loot. And say I won it twice in a row (which is certainly possible with random numbers). If I won it a third time in a row you would probably complain to the game manufacturers that their random number generator is faulty. So they take care that the same number doesn't come up too often in a row, even if that defeats true randomness.

Example reference:

Reseeding won't help jSepia's concern, which is really about runs rather than repetition. Pure randomness does lead to unfun gameplay, so it's a real concern and plenty of games have addressed it.

Also:

One thing you may want to look into is a Streak Breaker for continued series of randoms. If your game has a “chance to hit” variable on combat, putting a Streak Breaker in can take some of the sting out of missing in a long series of misses by ensuring the next attack is autohit.

Sorry about that. I'm a bit distracted today. Swapped my 15 year old truck for one with ... 3.4 miles! Got pickup on the brain.