Quick Lua math question

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Quick Lua math question

Post by Taehl »

What's wrong with that is, it produces the screenshot above. It doesn't look random at all. With a bit of tweaking, I can actually get the tile selections to go in straight rows, as if it was a mere modulo thing instead of pseudorandom.

If it's supposed to give me NANs, why do I get numbers like 131072, 16777216, and 134217728 passing through my modulo operation?
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
User avatar
bmelts
Party member
Posts: 380
Joined: Fri Jan 30, 2009 3:16 am
Location: Wiscönsin
Contact:

Re: Quick Lua math question

Post by bmelts »

Here's the problem with your math.random code: you're reseeding math.random every time.

On some platforms (including, apparently, yours), the first random result after seeding Lua's RNG is not very random at all. It generally remains constant across similar seeds, and can foul up an otherwise fairly random distribution if you reseed a lot.

You have two options, then:

1) seed the RNG once, and just call math.random each time, which will give you the standard rand() distribution
2) do what you're doing with the multiple reseeds, but call math.random an extra time before getting the value and applying it - that'll discard the junk number and give you a more random result.

I guess the third option is write your own generator, but that seems like a lot of unnecessary work.
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Quick Lua math question

Post by Taehl »

I already tried your method 2, anjo. That picture was taken with two pre-math.random calls before choosing the tiles. I was rather surprised by the result. So I'm stuck with method 3.
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Quick Lua math question

Post by Robin »

The main problem is that you seed every time. Of course the results don't look very random then.

At the beginning of your code, call math.randomseed(os.time()). When you need a random number, call math.random(min, max)
Help us help you: attach a .love.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Quick Lua math question

Post by vrld »

Taehl wrote:What's wrong with that is, it produces the screenshot above.
I was actually referring not to your implementation, but this:

Code: Select all

function math.drand(seed, min, max) 
    math.randomseed(seed)
    math.random(min, max)
end
It meets your requirement:
Taehl wrote:it requires that I can make a deterministic chain of pseudorandom numbers for any given coordinate.
The seed could be something like y * with + x.
Taehl wrote:If it's supposed to give me NANs, why do I get numbers like 131072, 16777216, and 134217728 passing through my modulo operation?
Your implementation with math.sinh is not well suited for pseudo random numbers. Look at this plot of sinh(x):
Image
You can see that the values of sinh(x) get really big really fast. It's already about 10000 for x = 10 and you are using numbers up to 999. Wolframalpha says this number is bigger 10^433 (a 1 with 433 zeros!)

Lua uses doubles as number type (at least on a PC/Mac). But a double cannot handle numbers that big. In fact, the bigger the number gets, some strange things happen. Adding a small number to a big number does not change the value; the small number gets "eaten". Some big (as well as some really small) numbers cannot be represented properly.
A combination of these and other effects could lead to your result.

If you absolutely do not want to use math.random() in combination with math.randomseed() to get predictable numbers, you could use the Middle-square method. The quality (= time to get to the same number with which you started is small) of this method is worse than what math.random() uses, but as you reseed for every cell anyway, it should not be a problem (it will be slower than the provided random though).
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Quick Lua math question

Post by Taehl »

Robin wrote:The main problem is that you seed every time. Of course the results don't look very random then.

At the beginning of your code, call math.randomseed(os.time()). When you need a random number, call math.random(min, max)
That's no good - a given coordinate must always return the same list of pseudorandom numbers. If I put os.time in the mix, the list will always be different.
vrld wrote:
Taehl wrote:What's wrong with that is, it produces the screenshot above.
I was actually referring not to your implementation, but this:

Code: Select all

function math.drand(seed, min, max) 
    math.randomseed(seed)
    math.random(min, max)
end
It meets your requirement:
Taehl wrote:it requires that I can make a deterministic chain of pseudorandom numbers for any given coordinate.
The seed could be something like y * with + x.
I know, but that's exactly the method I was using when I made that screenshot.
vrld wrote:
Taehl wrote:If it's supposed to give me NANs, why do I get numbers like 131072, 16777216, and 134217728 passing through my modulo operation?
Your implementation with math.sinh is not well suited for pseudo random numbers. Look at this plot of sinh(x):
Image
You can see that the values of sinh(x) get really big really fast. It's already about 10000 for x = 10 and you are using numbers up to 999. Wolframalpha says this number is bigger 10^433 (a 1 with 433 zeros!)

Lua uses doubles as number type (at least on a PC/Mac). But a double cannot handle numbers that big. In fact, the bigger the number gets, some strange things happen. Adding a small number to a big number does not change the value; the small number gets "eaten". Some big (as well as some really small) numbers cannot be represented properly.
A combination of these and other effects could lead to your result.
Aah, neat. That makes sense. The sinh thing doesn't hold any significance, I was just trying out random math calls until I found one that looked like it produced some wild numbers. I could use anything, really.
vrld wrote:If you absolutely do not want to use math.random() in combination with math.randomseed() to get predictable numbers, you could use the Middle-square method. The quality (= time to get to the same number with which you started is small) of this method is worse than what math.random() uses, but as you reseed for every cell anyway, it should not be a problem (it will be slower than the provided random though).
Not bad, that's pretty neat. Is there any way to implement that that doesn't require making it a string, messing with it, and making it a number again (i.e., is slow)?
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Quick Lua math question

Post by Robin »

Taehl wrote:
Robin wrote:The main problem is that you seed every time. Of course the results don't look very random then.

At the beginning of your code, call math.randomseed(os.time()). When you need a random number, call math.random(min, max)
That's no good - a given coordinate must always return the same list of pseudorandom numbers. If I put os.time in the mix, the list will always be different.
Ah, I didn't know. (Why do you want to do that, may I ask?)

And have you tried seeding by doing: math.randomseed(X_OF_TILE * 493 + Y_OF_TILE * 29302)? I just made up the two constant numbers. They might need to be primes, but I'm not sure. They are probably preferably large and very different from each other. I don't know if it'll work.
Help us help you: attach a .love.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Quick Lua math question

Post by vrld »

Taehl wrote:I know, but that's exactly the method I was using when I made that screenshot.
What do you use to calculate the seed for a given tile? Maybe the error is in there.
Taehl wrote:Is there any way to implement that that doesn't require making it a string, messing with it, and making it a number again (i.e., is slow)?
There is one that does not require messing with it, once it is a string:

Code: Select all

local seed = 58008
function msrand(digits)
    local r = seed * seed
    local pad = math.floor( (#tostring(r) - digits) / 2 )
    if pad > 0 then
        r = math.floor(r / math.pow(10, pad)) % math.pow(10, pad)
    end

    if r == 0 or r == 1 then
        seed = 5138008
    else
        seed = r
    end
    return r
end
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Quick Lua math question

Post by kikito »

Taehl wrote:
Robin wrote:The main problem is that you seed every time. Of course the results don't look very random then.

At the beginning of your code, call math.randomseed(os.time()). When you need a random number, call math.random(min, max)
That's no good - a given coordinate must always return the same list of pseudorandom numbers. If I put os.time in the mix, the list will always be different.
mm... what about setting the seed to a fixed value then?

Code: Select all

-- at the beginning of your code
math.randomseed(314159265)
When I write def I mean function.
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Quick Lua math question

Post by Taehl »

Better, but each coordinate needs a different list of pseudorandom numbers. They don't have to be very strong, but they do need to be different enough that a human won't see repetitions. Hence, I was trying to seed with a number derived from the coordinates.

By the way, for anyone else who wants to make suggestions on that front, please note that my coordinates are three-dimensional (my project-in-progress is 3D (even if it uses 2D graphics)).
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 1 guest