Bug In Renoise/Lua Math.Random Library?

On OSX, if I run this code 50 times:

  
math.randomseed(os.time())  
local test = {"a", "b", "c", "d", "e", "f", "g"}  
for i = 1, 5 do  
 prefix = math.random(1, #test)  
 prefix = test[prefix]  
 print(prefix)  
end  
print("---")  
  

The first value is always “a”

This is wrong, I expect the first value to be random.

If I remove math.randomseed(os.time()) it works as expected.

What is going on?

When you call math.randomseed() then (I assume) you are resetting the seed of the random number generator. When you reset the seed to a specific number, then the number generator will output the same, predictable sequence of pseudo-random numbers every time. I think the problem here stems from the os.time() function, which is not accurate enough to give you a unique value every single time you call it (within such a short amount of time).

For example:

for i = 1, 50 do  
 print(os.time())  
end  

This will (probably) output the same value for all 50 iterations, because the result of the os.time() function simply isn’t accurate enough to produce a different value each time it is called in this way.

Something like this might work a bit better:

math.randomseed(os.time())  
local test = {"a", "b", "c", "d", "e", "f", "g"}  
for x = 1, 50 do  
 for i = 1, 5 do  
 prefix = math.random(1, #test)  
 prefix = test[prefix]  
 print(prefix)  
 end  
 print("---")  
end  

You only need to call math.randomseed() once per session.

Yes, I understand what a random seed is, maybe you were explaining this for the benefit of other, but the behaviour is wrong.

If I run your code 50 times, i’ll get 250 prints, but the first print is always “a”. (Actually, now it’s always “b” because the seed is a bit higher, let’s rephrase that to “first value is always the same”)

Let’s look at it differently, here are two different values of os.time()

1283628570
1283629982

Run this code:

  
local test = {"a", "b", "c", "d", "e", "f", "g"}  
  
math.randomseed(1283628570)  
for i = 1, 5 do  
 prefix = math.random(1, #test)  
 prefix = test[prefix]  
 print(prefix)  
end  
print("---")  
  
math.randomseed(1283629982)  
for i = 1, 5 do  
 prefix = math.random(1, #test)  
 prefix = test[prefix]  
 print(prefix)  
end  
print("---")  
  

Notice that the first value of both are identical.

Either the seeds are being truncated, or os.time() is a terrible seed due to the way Lua works and I need something better.

-=-=-

Actually, I just googled it, and it may be OSX specific.

All spelling mistakes are final and will not be refunded.

A good explanation of my problem, here:

http://lua-users.org/lists/lua-l/2007-03/msg00564.html

The tip I will probably use for my code:

Just to empty the buffer, so to speak.

I apologise if anything sounded condescending, because that was definitely not my intention at all. I realise that you are an intelligent dude, but not everyone is quite so nerdy to understand pseudo-random number generators! I thought I would mention it, just in case. :)

The output I get (from Windows XP) is:

  
c  
c  
d  
g  
e  
---  
d  
d  
b  
g  
a  
---  
  

… so you could be right here, and this may be an OSX problem.

Hrm!

This works for me:

  
 math.randomseed(os.time())  
 local garbage = math.random()  
 garbage = math.random()  
 -- Back to normal  
  

Calling math.random() a couple of times before actually using avoids blatant similarities.

Works for me in the context of NotesRandomizer on OSX.

My problem was identical values, i think the discussion on that wiki page is about “true randomness”, but for my script i’m happy to live with “fake” over “not random” ;)

I already experienced this problem long time ago…
I solved it this way back then:

  
function randomize(tstart, tend)  
 local number = tostring(os.clock())  
 if string.find(number,"%.") ~= nil then  
 number = string.sub(number, string.find(number,"%.")+1)  
 end  
 math.randomseed( tonumber(number))  
 number = number + math.random(1, 7)  
 math.randomseed( tonumber(number))  
 math.random(tstart, tend); math.random(tstart, tend); math.random(tstart, tend)  
 local result = math.random(tstart, tend)  
 return result  
end  
  

When looking at it again… i guess the whole monkeybusiness before the three math.random(tstart, tend) calls seem measures in vain as calling this function three times most likely was enough…