X-platform random numbers
Monkey Forums/Monkey Programming/X-platform random numbers
| ||
Given the same Seed value, does Monkey generate the same sequence of random numbers regardless of target, OS, and hardware platform? Looks like it *almost* does (for X-target on same hardware, at least), except for the representation of floating point numbers issue. Can some of you run the following code and let me know if your results match up with mine? Strict Function Main:Int() Seed = 1000 For local n := 1 To 10 Print Rnd(0, 100) Next Return 0 End My results: HTML: 62.36203908920288 98.23320508003235 52.78060436248779 68.4232771396637 85.03351211547852 33.26745629310608 38.07581663131714 79.29973602294922 22.291147708892822 3.0291080474853516 C++ Tool: 62.362039089202881 98.233205080032349 52.780604362487793 68.423277139663696 85.033512115478516 33.267456293106079 38.075816631317139 79.299736022949219 22.291147708892822 3.0291080474853516 GLFW2 and GLFW3: 62.362037658691406 98.233207702636719 52.780605316162109 68.42327880859375 85.03350830078125 33.2674560546875 38.075817108154297 79.299736022949219 22.291147232055664 3.0291080474853516 (Desktop PC running Windows 8.1) So this means if you wanted to procedurally generate a game level that is consistent across multiple targets, you would use only the integer portion of the generated numbers in your calculations? |
| ||
I have had consistent results using integers across Android, iOS, HTML5, Flash, PC, and Mac. |
| ||
Okay, thanks Raph. |
| ||
Intel i7 running 64 bit Linux C++ 62.362039089202881 98.233205080032349 52.780604362487793 68.423277139663696 85.033512115478516 33.267456293106079 38.075816631317139 79.299736022949219 22.291147708892822 3.0291080474853516 GLFW 62.362037658691406 98.233207702636719 52.780605316162109 68.42327880859375 85.03350830078125 33.2674560546875 38.075817108154297 79.299736022949219 22.291147232055664 3.0291080474853516 HTML 62.36203908920288 98.23320508003235 52.78060436248779 68.4232771396637 85.03351211547852 33.26745629310608 38.07581663131714 79.29973602294922 22.291147708892822 3.0291080474853516 With out more testing. I would say that at float consistency would be that same for at least 3 or 4 digits for the factional part. |
| ||
It's looking like the platforms are storing the numbers in an identical fashion, but printing them out differently! At least that's the only explanation I can think of, because if the actual values differed, surely the difference would rapidly be amplified until the results were completely different? Years ago I wrote an integer rand() function that emulates MSVC rand(), so if you are worried you could consider using it: http://www.monkey-x.com/Community/posts.php?topic=1568 |
| ||
Thanks dawlane. Just to be extra cautious, I'd use the integer portion only, none of the fractional... Gerry, you may be correct... I'm not sure what Monkey uses for its algorithm (I haven't looked into the source), but the industry standard seems to be http://en.wikipedia.org/wiki/Mersenne_twister. IIRC, Brucey coded a version of Mersenne Twister for BlitzMax ages ago... Could probably port that... |
| ||
Agreed. A LOT of my games use seeded-randomisation to build levels and things. For the most part, I've not noticed any differences, but I tend to use mostly ints, and not delve too deep into the floating points. I'd say that you're pretty much safe to assume it's ok, and is "mostly" identical on all platforms, as long as you don't allow it to get "too" precise. .. But then, if we're honest, even exact pre-determined numbers can get fuddled when monitored at such high precision. That's just one of those things we all have to be aware of. There are FAR worse things that can happen when dealing with multiple targets. .. (Stupid Android image dithering, breaking my data methods.. grrr..) |
| ||
At a glance the differences between platforms are roughly on the order of ("correct value")/(10^8). This suggests that the actual double precision values have been converted to single precision, then back to double. I suppose it's related to issues raised in this old discussion: http://www.monkey-x.com/Community/posts.php?topic=1566&page=1 |
| ||
if the actual values differed, surely the difference would rapidly be amplified until the results were completely different? The random number generator produces a sequence of 32-bit integers. I believe JavaScript emulates this via double precision. But assuming it is done correctly there should be no difference between platforms. These integer values are then massaged to produce values for Rnd(). That's where the differences arise. Here's the source for monkey.random, from 75d. ( I'm not keeping up with developments. ) ' Module monkey.random ' ' Placed into the public domain 24/02/2011. ' No warranty implied; use at your own risk. Private Const A=1664525 Const C=1013904223 Public Global Seed=1234 'Note: Freaky '|0' below is a work around for Js not having a real int type. ' 'Should probably be & $ffffffff? Think about it later! ' Function Rnd#() Seed=(Seed*A+C)|0 Return Float(Seed Shr 8 & $ffffff)/$1000000 End Function Rnd#( range# ) Return Rnd()*range End Function Function Rnd#( low#,high# ) Return Rnd( high-low )+low End |
| ||
81b has the same source code. Thanks for your insight, Floyd. Another thing I've noticed is if you want to seed with Millisecs() you need to explicitly import it from mojo.app. Not a problem for those of us with a Pro license, but for those who don't... Time to roll your own Millisecs() functions... ;) EDIT: Actually, you have to create a proper Mojo app to make use of the Millisecs() function. This will NOT compile: Strict Import mojo.app Function Main:Int() Seed = Millisecs() For Local n := 1 To 10 Print Rnd() Next Return 0 End A shame... Unless I'm overlooking something obvious... . |
| ||
What has the Pro license got to do with it? Unless people are using Monkey language without mojo for a wide variety of targets. Are they? In any case , the diddy module also has a Millisecs function, so if so, this should be the least of their troubles! |
| ||
Heh, I just realized my example wasn't working because my target was set to "c++ tool". *facepalm* @Gerry: You answered your own question. The Pro license gives you Mojo which gives you Millisecs(). So the Pro license has everything to do with that. But I agree with your other points... |
| ||
The free version of Monkey already comes with the HTML5 and GLFW implementations of Mojo. This means it comes with the 'mojo.app' module, and therefore has 'Millisecs'. The version of Monkey you're running doesn't change the fact that Mojo only works on supported game-targets. So, the STDCPP / C++ Tool target doesn't come with it by default. That being said, as Gerry Quinn mentioned, Diddy comes with its own implementation, from what I remember, anyway. I also made a module for this (Along with the old 'Delay' command). |
| ||
The free version of Monkey already comes with the HTML5 and GLFW implementations of Mojo. Well, there you go. That was not the case in the early Monkey/Mojo days. Today I learned I'm further behind the times than I thought! Apologies to Gerry... ... Mojo only works on supported game-targets. So, the STDCPP / C++ Tool target doesn't come with it by default. That I *do* already know. Hence the *facepalm* at my foolishness trying to run the above code on that target. :) |
| ||
Diddy has a RandomSource class that functions similarly to Java's Random class. It uses Monkey's built-in Rnd() function but with a bunch of helper methods and the ability to cache seeds. Code: https://code.google.com/p/diddy/source/browse/src/diddy/math.monkey Sample: https://code.google.com/p/diddy/source/browse/examples/RandomSource/testRandomSource.monkey |