Page 2 of 5

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 1:58 am
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?

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 2:05 am
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.

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 2:07 am
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.

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 6:50 am
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)

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 11:12 am
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).

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 7:09 pm
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)?

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 7:33 pm
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.

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 7:52 pm
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

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 10:16 pm
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)

Re: Quick Lua math question

Posted: Thu Nov 11, 2010 11:20 pm
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)).