Sinisterly
[Lua] rand.lua - an alternative to the not so random math.random() in-built function - Printable Version

+- Sinisterly (https://sinister.li)
+-- Forum: Coding (https://sinister.li/Forum-Coding)
+--- Forum: Coding (https://sinister.li/Forum-Coding--71)
+--- Thread: [Lua] rand.lua - an alternative to the not so random math.random() in-built function (/Thread-Lua-rand-lua-an-alternative-to-the-not-so-random-math-random-in-built-function)



[Lua] rand.lua - an alternative to the not so random math.random() in-built function - noize - 08-02-2013

I often happened to find troubles in the randomness of math.random(). After some researches I found out it's a pretty common issue.

http://stackoverflow.com/questions/461978/why-is-the-first-random-number-always-the-same-on-some-platforms-in-lua

You could as well google "lua math.random not random" or whatever and look at the results.

This is why I just coded a pseudo-random number generator function.

Code:
function rand(floor,ceil) -- rand.lua -- -- pseudo-random number generator (PRNG) version 0.1 (beta) -- an alternative to the mostly sloppy math.random() -- -- you are allowed to use, edit or redistribute this code in whole or part as long as you give credits -- -- lua 5.1 -- authored by noize assert(tonumber(floor) == floor,"error: floor needs to be a number.") assert(tonumber(ceil) == ceil,"error: ceil needs to be a number.") -- instead of using the type() function I use this method as it lets nil values pass as well local n = {} math.randomseed(os.time()) n.r = math.random(65535) / (os.time() + os.clock()) n.x = n.r * os.time() * os.clock() if os.time() >= 1200000000 then n.a = n.x * math.sqrt(n.r) / os.clock() * os.time() else n.a = (n.x / 2) * n.r ^ 3 / os.clock() * os.time() end n.j = math.random(math.random(),math.sqrt(math.random()) + math.random() * os.clock()) n.k = math.random(math.random(),math.random() / math.random() * os.time()) if math.random() > 0.54 then if math.random() > 0.78 then n.a = n.a * math.random( n.j, n.j + math.random(math.random(1,2),math.sqrt(math.random())+math.random()*os.clock()/math.random()) ) else n.a = n.a * math.random( math.sqrt(math.random( math.random(), math.sqrt( math.random() + math.random() + os.clock() ^ (math.random() + math.random() + math.random()) / (math.random() + math.random()) + math.random() ) * math.random() )) * math.sqrt(math.random()), math.sqrt(math.random()) + math.sqrt(n.j) + math.random( math.random(1,2), math.sqrt(n.j) / math.random() + ((math.random() + math.random()) / (math.random() + math.random() + math.random() + math.random())) ) / math.sqrt(math.random()) ) end else if math.random() > 0.78 then n.a = n.a * math.random( n.k, n.k + math.random(math.random(1,2),math.sqrt(math.random())+math.random()*os.time()/os.clock()/math.random()) ) else n.a = n.a * math.random( math.sqrt( (n.k - (math.random() * n.k)) + math.sqrt(n.k) + math.random( math.random(0,1), math.sqrt( n.k + (math.random() + math.random() + math.random() + math.random()) / ((math.random() + math.random()) * os.time() ^ ((math.random() + math.random() + math.random()) / (math.random() + math.random()))) ) ) ), tonumber( math.random() + n.k + math.random( math.random(1,2), math.sqrt( math.random(1,2) + math.random() + os.clock() ^ (math.random() + math.random() + math.random() + math.random()) / math.sqrt(math.random() + math.random() + math.random() * 3) ) / math.sqrt(math.random()) ) ) ) end end if n.a == 0 then n.a = math.random() end n.a = n.a * math.sqrt(math.random(1,10)) if floor == nil and ceil == nil then return n.a elseif floor == nil then while n.a > ceil do math.randomseed(os.time() * os.clock() ^ os.time()) n.a = n.a / math.sqrt(os.clock() - math.sqrt(os.clock() - math.random())) end return n.a elseif ceil == nil then while n.a < floor do math.randomseed(os.time() * os.clock() ^ os.time()) n.a = n.a * math.sqrt(os.clock() - math.sqrt(os.clock() - math.random())) end return n.a else assert(floor < ceil,"error: floor needs to be lower than ceil.") while n.a > ceil or n.a < floor do if n.a > ceil then math.randomseed(os.time() * os.clock() ^ os.time()) n.a = n.a / math.sqrt(math.sqrt(os.clock())) end if n.a < floor then math.randomseed(os.time() * os.clock() ^ os.time()) n.a = n.a * math.sqrt(math.sqrt(math.random())) end end return n.a end end

To call it you can add the code in your script or save it as rand.lua and then use:

Code:
require("rand") -- or as well dofile("rand.lua")

require() should work better. Call the function:

Code:
rand(1,10) -- this will return a pseudo-random number between 1 and 10 math.floor(-rand(100,1000)) -- this will return a pseudo-random integer between -1000 and -100 print(rand(nil,99)) -- this will output a pseudo-random number between 0 and 99 print(math.ceil(rand(3,nil))) -- this will output a pseudo-random integer betwen 3 and, theorically any number (practically, you will see there is a limit) rand(nil,nil) -- this is in theory the most random possibility with rand()

This is still buggy, I'll definitely work on this, will get this better. Sometimes, when you use the function twice in a very short time, you might get two some similar numbers, because of the binding to os.clock()/os.time(). There are a few chances that the function will die and show an error message, I reduced a lot the times it should occur.

Please, let me know about how the statistics go for you; if you quickly call the function many times, how many and in how short times does the function return fairly similar numbers? How many times do you get errors? How about performance? Maybe a comparation to math.random()?


RE: [Lua] rand.lua - an alternative to the not so random math.random() in-built function - Ex094 - 08-17-2013

Did you read any books etc before making that generator? I'm trying to make one of my own too but having a Hard Luck with that


RE: [Lua] rand.lua - an alternative to the not so random math.random() in-built function - Ex094 - 08-17-2013

Did you read any books etc before making that generator? I'm trying to make one of my own too but having a Hard Luck with that


RE: [Lua] rand.lua - an alternative to the not so random math.random() in-built function - Deque - 08-17-2013

What are you doing there? It looks to me like you do some random calculations that just came into your mind. And why do you use math.random in order to replace math.random? That doesn't look like a good idea to me.

You can instead really create pseudo random number generator. Some algorithms are described here: https://en.wikipedia.org/wiki/Random_number_generation

Have a look at this video from numberphile which explains one of the most common (and easy) algorithms, the linear congruential generator: http://www.numberphile.com/videos/random_numbers.html


RE: [Lua] rand.lua - an alternative to the not so random math.random() in-built function - noize - 08-17-2013

(08-17-2013, 08:06 AM)Ex094 Wrote: Did you read any books etc before making that generator? I'm trying to make one of my own too but having a Hard Luck with that

Indeed the answer has been given by Deque:

(08-17-2013, 08:11 PM)Deque Wrote: you do some random calculations that just came into your mind

That's indeed just more random than math.random is. math.random appears to often give the same numbers, even changing math.randomseed. This one, very less often, but a time in (actually, now) quite many, this will crash in an error.

I thought like "how about reading something about RNGs first?" actually, but you know what the answer was. Now I'll just try to make a real RNG.