3

I am supposed to verify the capability of the random number generator of our implementation of Lua.

This is what I came up with...

 for i = 1,10000 do                         -- I hope that's ten thousand

 X = math.random(0,9)

 if     X == 0 then This_Many_0 = This_Many_0 + 1
 elseif X == 1 then This_Many_1 = This_Many_1 + 1
 elseif X == 2 then This_Many_2 = This_Many_2 + 1
 elseif X == 3 then This_Many_3 = This_Many_3 + 1
 elseif X == 4 then This_Many_4 = This_Many_4 + 1
 elseif X == 5 then This_Many_5 = This_Many_5 + 1
 elseif X == 6 then This_Many_6 = This_Many_6 + 1
 elseif X == 7 then This_Many_7 = This_Many_7 + 1
 elseif X == 8 then This_Many_8 = This_Many_8 + 1
 elseif X == 9 then This_Many_9 = This_Many_9 + 1

 else               Bogus_Alert = True      -- Better not happen

 end                                        -- End the big if/elseif block

 The_Interim_Sum = The_Interim_Sum + X      -- Keep a running sum

 end                                        -- This is the i loop

I then printed the results, here they are...

 Running
 Number of times we got 0  ...  1019
 Number of times we got 1  ...  979
 Number of times we got 2  ...  954
 Number of times we got 3  ...  1006
 Number of times we got 4  ...  995
 Number of times we got 5  ...  999
 Number of times we got 6  ...  989
 Number of times we got 7  ...  1000
 Number of times we got 8  ...  1042
 Number of times we got 9  ...  1017
 The sum of the ten thousand random numbers was 45303
 The average of those numbers was 4.5303
 End

These follow my expectations; i.e., the average is very close to 4.5, and the distribution of each individual number is close to one thousand.

More to the point, with numbers like these, I say that yes indeed, that generator is doing a very good job of really making ten thousand random numbers that really are random.

Here's the point of confusion: my boss says that if the machine is truly doing its job, and truly giving us random numbers, then the distribution of each number should be even; i.e., in ten thousand iterations, I should get precisely one thousand of each digit.

I tried adding math.randomseed(os.time()) before the loop which was using X = math.random(0,9) based on some other conversations here on StackOverflow. The results were further off, not closer.

I took out the math.randomseed(os.time()) line, ran the test again, and got an average of 4.5007 (which is the best I've seen yet).

So, what have I discovered ? Anything ? Nothing ? A random number generator is really a *pseudo*random number generator ? Everybody already knows that.

Have I demonstrated that this pseudo random number generator is about as random as we can expect ?

Do I have reason to fear using these values ? I'm going to take pot shots at a routine and give him deliberately bad numbers. The full range is too much for testing each and every case. I'm guessing that properly distributed, 16K potshots will give me the confidence that the chip is handling the (purposely bad) values properly.

(Note for the reader, I'm doing V&V on a multiprocessor system, and my Lua scripts are faking the behavior of one of the parts of the system which we don't have yet.)

Is there a way that I can get Lua to generate exactly one thousand of each number in this case with the math.random() function ?

If so, would that truly be random ?

User.1
  • 2,562
  • 3
  • 33
  • 40
  • 2
    Why would you expect a truly random distribution to produce equal quantities of every number? While an even distribution is the most likely *specific* outcome, you are still far less likely to see it than to see one of the many non-equal distributions of numbers. – Mankarse Mar 13 '14 at 07:44
  • 5
    Your boss doesn't have necessary knowledge in probability theory. – Egor Skriptunoff Mar 13 '14 at 07:48
  • Okay, so, for taking V&V pot shots, what I have now is random enough; yes ? – User.1 Mar 13 '14 at 07:53
  • 1
    Real entropy is almost only useful to protect against malicious intent. That means, for security applications. In all likelihood for verifying your system, `math.random` will be enough with `os.time` as seed. Sometimes you will find it is even better to have a predefined seed. If you don't think that is not enough, a formal proof of your system is probably more useful. – dualed Mar 14 '14 at 21:45
  • @dualed Your comment is quite sensible. +1 for you – User.1 Mar 15 '14 at 14:08

3 Answers3

4

First, you need to run math.randomseed() once before using math.random(), and it's better to throw away the first few random numbers because the first few are not that random in some implementations, see Lua math.random not working for detail.

math.randomseed(os.time())
math.random(); math.random(); math.random()

Second, even if you are flipping a perfect balanced coin for one thousand times, you don't usually get precisely 500 times of head and 500 times of tail. It's just the probability of getting a head is about 500. If the experiments are done for many many times, you would expect the average of head being 500, but again, not precisely 500 every time.

Third, yes, math.random() is a psudo random number generator. In fact, you can't generate real random numbers using computers only. The Lua math.random() is using the C library function rand() internally. And it's true that the C rand() function is NOT a good random number generator. If randomness is important, use some better methods to implement, e.g, the C++ random engine, or dev/random on Linux, etc.

Community
  • 1
  • 1
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • I read that, and I neglected to throw away the first few numbers in my experiment. Thank you for reminding me. I should not be up at 3 and 4 in the morning. I'm going to sleep. – User.1 Mar 13 '14 at 07:59
  • 1
    `std::uniform_int_distribution` is not a random number generator, it merely post-processes random numbers to make the resulting distribution adhere to certain distribution properties. It does not add any entropy to the result though (for instance, feeding `rand` values to a distribution will still give crappy randomness). The actual random number generators in C++ are known as engines (`std::random_device` or `std::mt19937`). Mind that usually you need _both_ the correct engine and the right distribution to get the numbers you want. – ComicSansMS Mar 13 '14 at 10:33
  • FYI, there's no such thing as **real random numbers**. Any PNRG will produce some discrepancies. – dns Jan 07 '21 at 07:57
4

A remarkable simple test is to use the random number sequence as (x, y) or (x, y, z) coordinates and plot them. Here are some real world examples of this:

mvw
  • 5,075
  • 1
  • 28
  • 34
3

There are other tests than frequency. See http://en.wikipedia.org/wiki/Statistical_randomness. You may want to try them.

If you want a random number generator for Lua with known properties, try lrandom, which is based on the Mersenne Twister.

lhf
  • 70,581
  • 9
  • 108
  • 149