Page 1 of 2

Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 8:39 am
by Helvecta
I'm checking out some of the features for 0.9 and the RNG doesn't want to play nice. Running the following (the wiki's example and an assertion to check the outcome) always returns "9". Since this is the wiki's example, I figure it should be more... random.

Code: Select all

function love.load()
    rng = love.math.newRandomGenerator()
    rng:setSeed(os.time())
    randomNumber = rng:random(1,100)
    assert(nil, randomNumber)
end
Can someone lay the knowledge smackdown on me? Thanks.

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 8:48 am
by slime
Does this give something more random?

Code: Select all

function love.load()
    rng = love.math.newRandomGenerator()
    rng:setSeed(os.time())
    rng:random()
    randomNumber = rng:random(1,100)
    assert(nil, randomNumber)
end
Or maybe this:

Code: Select all

function love.load()
    rng = love.math.newRandomGenerator()
    rng:setSeed(tonumber(tostring(os.time()):reverse()))
    randomNumber = rng:random(1,100)
    assert(nil, randomNumber)
end

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 1:51 pm
by Helvecta
What on Earth..

Your first example runs like clockwork in reverse, decrementing by one every time I run it (I set the RNG to output a number between 1 and 10 and run the file roughly once a second); the second one only gives numbers between 1 and 6 when set up the same way, and seems to increment by one each time I run it. I suppose that's since the seed is based on os.time(), and I'm starting the application roughly once every second, but the random number shouldn't be incrementing by one just because os.time() is incrementing by one.. right!?

Output, first example:

Code: Select all

8, 8, 7, 6, 5, 4, 3
Output, second example:

Code: Select all

1, 2, 3, 4, 5, 6, 1

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 2:20 pm
by bartbes
Unfortunately the algorithm used (xorshift) produces very similar initial results for similar seeds, they should diverge, though.

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 2:37 pm
by Helvecta
Oh, alright; I suppose needing an RNG within the first couple seconds of an app's execution does seem unlikely, so I can live with that.

But what about this function?

Code: Select all

function Random(min, max, isFractional)
	local gen = love.math.newRandomGenerator()
	gen:setSeed(os.time())
	local isFractional = isFractional or false
	local randomNumber
	if isFractional == true then
		randomNumber = gen:random(min * 100, max * 100) / 100		-- math random doesn't play nice with decimals..
	else
		randomNumber = gen:random(min, max)
	end
	assert(nil, randomNumber) -- some debug junk
	return randomNumber
end
the purpose of the function is to return a random number, but with support for decimals (maybe I'm wrong but playing with random suggests that it doesn't do decimals).

However, everytime I call the function,

Code: Select all

Random(- 5, 5, true)
the assertion returns -4.2, every time. Every time!


Something's funky here, but what? And why? :o:

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 3:15 pm
by bartbes
Well, you're seeding too much, mostly.

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 4:08 pm
by Helvecta
I thought that :setSeed was necessary when setting up the RNG but reading other stuff is agreeing with what you're advising. I guess by now you're figuring out that I'm not familiar with what makes an RNG less predictable. :crazy:

Okay, so I need to reseed less, but I have nowhere else to set the seed since the RNG it's effecting is local and called in the function, so I'll just get rid of that line (removed: gen:setSeed(os.time())). Doing this has little effect; the RNG just spits out -0.26 at this point.

So looking back at Slime's post, I decide I should try to emulate it and generate a random number before I generate a random number (added: gen:random()), making the RNG spit out 3.35. Setting the seed again (added: gen:setSeed(os.time())) makes the number change each time, but it follows a predictable time-based pattern, running backwards from 5 to -5 (code below)

Code: Select all

function Random(min, max, isFractional)
   local gen = love.math.newRandomGenerator()
   gen:setSeed(os.time())
   gen:random()
   local isFractional = isFractional or false
   local randomNumber
   if isFractional == true then
      randomNumber = gen:random(min * 100, max * 100) / 100      -- math random doesn't play nice with decimals..
   else
      randomNumber = gen:random(min, max)
   end
   assert(nil, randomNumber) -- some debug junk
   return randomNumber
end
Why does it refuse to be random? :brows:

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 4:43 pm
by bartbes
So why does that RandomNumberGenerator need to be created there? You can create it elsewhere, or use the global one (love.math.random), that means you don't have to seed for every result.

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 4:44 pm
by Robin
A function that returns or uses a pseudo-random number should not mess with the seed. You could do something like this:

Code: Select all

local gen = love.math.newRandomGenerator()
gen:setSeed(os.time())
gen:random()

function Random(min, max, isFractional)
   local randomNumber
   if isFractional then
      randomNumber = gen:random(min * 100, max * 100) / 100      -- math random doesn't play nice with decimals..
   else
      randomNumber = gen:random(min, max)
   end
   assert(nil, randomNumber) -- some debug junk
   return randomNumber
end

Re: Another Question About 0.9's RNG

Posted: Fri Dec 20, 2013 5:25 pm
by Helvecta
bartbes wrote:love.math.random
Oh, that's perfect, thanks for throwing that my way, I didn't know that existed.
That begs the question though: why does all this stuff about RandomGenerators even exist if the same can be done with love.math.random? Is it because of the control over the generator's seed? I guess so that you could replicate seemingly random numbers if you needed to?
Robin wrote:A function that returns or uses a pseudo-random number should not mess with the seed.
I'll keep that in mind, thanks! I tested out the example you posted in LOVE though and it still seems to generate a number "like clockwork". Maybe it's because of the way I'm testing it, but I don't think that should matter.
I recorded a video of it, too, to show you what I'm doing.


Figuring out what differentiates this from love.math.random - and figuring out how to actually make RandomGenerator work - would help me a ton, so any info clearing this up would be appreciated. ^^