How to set the seed for Math.random() in Apex - apex-code

Is there a way to set the seed for the random number generator in Apex? And if so; which function do I use for it?

It likely isn't possible to seed the RNG in Apex. If you need a repeatable sequence of random numbers, you'll have to implement a seeded pseudo random number generator yourself.
On the Apex platform, I'm sure they have a huge source of entropy available to generate random numbers, and there's no need for you to seed the generator.

There is no way to seed the built-in random number generator in Salesforce. I was in the same boat as you. I wanted to be able to use a seed, so that I could create repeatable random numbers.
So, I thought I'd attempt to write my own RNG. I spent a number of days scouring the Internet for algorithms. I was able to piece together a pretty comprehensive library of functions borrowing from various sources. The classes are: "Random.cls", which is the main RNG class, and "Random_Test.cls", which is the test code.
It has the following methods:
nextInteger(upperLimit)
nextLong(upperLimit)
nextDouble(upperLimit)
nextUniform() - Same function as Math.Random() to return a Double between 0.0 and 1.0.
nextIntegerInRange(lowerLimit, upperLimit)
nextLongInRange(lowerLimit, upperLimit)
nextDoubleInRange(lowerLimit, upperLimit)
shuffle(List<Object>) - destroys the order of the original list
shuffleWithCopy(List<Object>) - return a shuffled copy of the list, in case you wish to preserve the list's original order (less efficient than "shuffle(List<Object>)")
The "Random.cls" documents the sources that I borrowed from in case you want to read more about random number generators.
I put the code out on GitHub for anyone who wants it: https://github.com/DeviousBard/Salesforce/tree/master

Related

Understanding random number generation

I'm creating a game where I want to create random worlds and give the player the option of having the same world made again by entering the same seed...
So... How can I do this? It will generate the same set of numbers, but not the same every time you call for the random function...
Do I have to make function of sorts based on the seed manually?
In GameMaker Studio and GameMaker 8.1 there is a function:
random_set_seed(seed)
Here you can enter your seed.
Then random(x) gives the same n-th result per game run.
random(100)
randomize() // This doesn't change rand[0] or rand[1]
random_set_seed(20) // because of this
rand[0]=random(100)
rand[1]=random(100)
Randomizer functions either use mathematical formulas which seem to give out random numbers or just look at an already calculated array of seemingly random numbers and return them in order. In most languages, there is a function which will look at the computer's clock and will use this value as a first value for the mathematical formula or as a starting index in the pseudorandom array. In GameMaker, you can use randomize() to do that. Only call that once when the game launches and you'll get different results on every execution.
If you want the opposite, that is you want to be able to regenerate the same seemingly random sequence, you can instead set the seed manually with random_set_seed(value). The value passed needs to be a number. Then you can give that seed to the player.
So if you want to generate a random level on the first time and later be able to replay the same level, you need to do in order:
Call randomize to set a random seed.
Call random_get_seed which will return the current seed.
Call random and the likes to generate a level.
When the player wants to use the same seed as before, call random_set_seed and pass it the seed.
Warning: By using those functions, you are putting your trust in GM's randomizing functions. These are platform dependent, and the functions might change in a later version of GM. If you want your seeds to work across all platforms and versions of your game, you might want to work on your own randomizing functions.

Random Number Generator that Allows "Indexing"

I hope it's not too obvious a question: is there a random number generation algorithm that doesn't depend on previously returned values, so that I can get (for example) the 50th number in the sequence, without computing the previous 49?
The reason is that I am making roguelike that will be persistent (so that I can recreate the exact same level from the same seed), but to compute certain features of each level, I don't want to have to "compute" all previous features just to get the random number generator to the correct "state" of having been used, for example, 100 times so far. I would like to be able to query the 101st random number without determining previous values so that the program can create level features separately.
You can encrypt ordinary sequence number [1..N] with any cipher,
and by this way - generate unique pseudorandom value for each SeqNo.
If you use a linear congruential random number generator, it is trivial to compute the $n$-th element generated from a given seed. But it is probably easier just to stash away the state at the "interesting" points of the game.
OTOH, if you want to "restart" the game at a certain point, you'll presumably want to be able to recreate the dungeon's features, but (due to different player actions) the RNG usage will be different from then on. I.e., if started at the same point, if I shoot twice at a monster the RNG will be used more times than if I just run away; the next item generated will get different values. Perhaps what you really want is several independent random number streams, and saving the states as needed?
There are lots of roguelike games around, mostly open source. Some are limited/small (from "build a game in a day" sort of competitions), and might make a good starting point for you. Why start your own, and not hack on an existing one?

Can't understand why I need to seed using srand

When we need a random number we use srand once to initialize the seed and after that we can use rand. Why do we need to seed using srand? For example srand(time(Null)); Can't we just use rand() % 99999? Am I missing something in the concept of these functions?
Here's the thing,
You actually don't need to seed your random number generator. Go ahead, try it without!
BUT, you will always get the same sequence of 'random' numbers.
Pseudo-random number generators such as rand() only generate random-looking sequences. If you just start them from the 'beginning' every time, they will of course look the same.
Seeding the generator is a good way to get numbers that actually appear 'properly' random. If you seed with the time, you are starting somewhere 'random' in the sequence. Note that picking time values close together usually gives two sequences that are also very different.
You can seed with whatever you like. For example, if you have lots of threads using lots of generators, the time is a bad idea because the time may well be the same for multiple threads.
There is no clear 'good' value for the seed, so it is usually not seeded by default. This can also be a good thing if you want to 're-run' a randomised algorithm with exactly the same input: just set the seed to be the same seed.
srand(0) will always return the same deterministic sequence of values, although those values will appear random.
Knowing your seed will allow an attacker to determine every number you generate.
By setting a seed, you effectively create a different sequence.
srand(0) may be entirely acceptable to your needs, if you only need the appearence of random.

Why are some random() functions deemed "not secure?"

I've heard people being warned all over the place not to rely on a language's random() function to generate a random number or string sequence "for security reasons." Java even has a SecureRandom class. Why is this?
When people talk about predicting the output of a random number generator, they don't even need to get the actual "next number". Even something subtle like noticing that the random numbers aren't evenly distributed, or that they never produce the same number twice in a row, or that "bit 5 is always set", can go a long way towards turning an attack based on guessing a "random" number from taking years, to taking days.
There is a tradeoff, generally, too. Without specific hardware to do it, generating large quantities of random numbers quickly can be really hard, since there isn't enough "randomness" available to the computer so it has to fake it.
If you're not using the randomness for security (cryptography, passwords, etc), but instead for things like simulations or numerical work, then it doesn't matter too much if they're predictable, only that they're statistically random.
Almost every random number generator is 'pseudo random' in that it uses a table of random numbers or a predictable formula. A seed is sometimes used to "start" the random sequence at a specific point, e.g. seedRandom(timer).
This was especially prevalent in the days of BAsIC programming, because it's random number generator always started at exactly the same sequence of numbers, making it unusable for any kind of GUID generation.
Back in the day, the Z-80 microprocessor had a truly random number generator, although it was only a number between 0 and 127. It used a processor cycle function and was unpredictable.
Pseudo-random numbers that can be determined in advance can lead to security holes that are vulnerable to a random number generator attack.
Predictability of a random number is a big issue. Most "random" functions derive their value from time. Given the right set of conditions you could end up with two "random" numbers of a large value that are the same.
In windows .NET world CPRNG (Cryptographically secure pseudo random number generator) can be found in System.Security.Cryptography.RandomNumberGenerator through underlying win32 APIs
In Linux there is a random "device"

Generate Array of Numbers that fit to a Probability Distribution in Ruby?

Say I have 100 records, and I want to mock out the created_at date so it fits on some curve. Is there a library to do that, or what formula could I use? I think this is along the same track:
Generate Random Numbers with Probabilistic Distribution
I don't know much about how they are classified in mathematics, but I'm looking at things like:
bell curve
logarithmic (typical biology/evolution) curve?
...
Just looking for some formulas in code so I can say this:
Given 100 records, a timespan of 1.week, and an interval of 12.hours
set created_at for each record such that it fits, roughly, to curve
Thanks so much!
Update
I found this forum post about ruby algorithms, which led me to rsruby, an R/Ruby bridge, but that seems like too much.
Update 2
I wrote this little snippet trying out the gsl library, getting there...
Generate test data in Rails where created_at falls along a Statistical Distribution
I recently came across croupier, a ruby gem that aims to generate numbers according to a variety of statistical distributions.
I have yet to try it but it sounds quite promising.
You can generate UNIX timestamps which are really just integers. First figure out when you want to start, for example now:
start = DateTime::now().to_time.to_i
Find out when the end of your interval should be (say 1 week later):
finish = (DateTime::now()+1.week).to_time.to_i
Ruby uses this algorithm to generate random numbers. It is almost uniform. Then generate random numbers between the two:
r = Random.new.rand(start..finish)
Then convert that back to a date:
d = Time.at(r)
This looks promising as well:
http://rb-gsl.rubyforge.org/files/rdoc/randist_rdoc.html
And this too:
http://rb-gsl.rubyforge.org/files/rdoc/rng_rdoc.html
From wiki:
There are a couple of methods to
generate a random number based on a
probability density function. These
methods involve transforming a uniform
random number in some way. Because of
this, these methods work equally well
in generating both pseudo-random and
true random numbers.
One method, called the inversion
method, involves integrating up to
an area greater than or equal to the
random number (which should be
generated between 0 and 1 for proper
distributions).
A second method, called the
acceptance-rejection method,
involves choosing an x and y value and
testing whether the function of x is
greater than the y value. If it is,
the x value is accepted. Otherwise,
the x value is rejected and the
algorithm tries again.
The first method is the one used in the accepted answer in your SO linked question: Generate Random Numbers with Probabilistic Distribution
Another option is the Distribution gem under SciRuby. You can generate normal numbers by:
require 'distribution'
rng = Distribution::Normal.rng
random_numbers = Array.new(100).map { rng.call }
There are RNGs for various other distributions as well.

Resources