![]() |
|
[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
endTo 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. |