Skip to content

Latest commit

 

History

History
391 lines (211 loc) · 11.8 KB

README.md

File metadata and controls

391 lines (211 loc) · 11.8 KB

Random - Better Random Number Generation for Grails

Description

This Grails plugin wraps the high-performance, statistically sound Uncommons Maths Pseudo-Random Number Generators in convenient, easy-to-use services and taglibs.

Why would I use this?

You may be asking yourself why you would ever install a highly specialized plugin when you can easily get a random number using java.util.Random with a single line of code. Although java.util.Random may suffice for many every-day randomization use-cases, there are at least 3 primary considerations to weigh when choosing to use this plugin (or the Uncommons Maths library):

  1. Quality - java.util.Random, while relatively fast, is inferior in the random quality of the numbers it generates. Over large distributions it exhibits significant periodic behavior that shatters any illusion of randomness, rendering it unsuitable for industrial-strength randomization purposes. The Uncommons Maths library provides alternative algorithms that produce higher-quality random numbers than java.util.Random.

  2. Speed - core Java contains an alternative to java.util.Random in java.security.SecureRandom. While this class fills the quality gap, it does so at a cost - in speed. Using SecureRandom may be up to 60 times slower than java.util.Random. Again, this may be suitable for most casual random-number needs, but for industrial strength usage, it may well fall far short of performance requirements. The Uncommons Maths library provides alternative algorithms that all perform faster than SecureRandom.

  3. Convenience - the Random Grails plugin provides a taglib and a service, making it dead simple to add industrial-strength randomization wherever your application should need it. If you've identified a need for shuffling lists, drawing random objects from a collection, or generating a random number from a specified range, you might as well do it the right way.

I found myself using Uncommons Maths for reasons 1 and 2 when it became clear that the core Java randoms would not suffice for my Random Bands experiment. I decided to package this as a plugin for reason #3 so that others might benefit.

Installation

Enter your application directory and run the following from the command line:

grails install-plugin random

After you have installed the Random plugin in your application, I'd recommend you point your browser to the Plugin test page to verify all is working and familiarize yourself with the functionality it provides:

http://localhost:8080/myAppContext/random

Configuration

The RandomPlugin may be configured with a single paramter, specified in your application's /grails-app/conf/Config.groovy

random.generator.default	= 'NAME_OF_PNRG_ALGORITHM'	// The PNRG Algorithm to use by default

random.generator.default

optional

Setting this to the name of an Uncommons Maths PRNG algorithm (as listed in the next section) specifies which Random Number Generator to use as a default. You may still provide an instance of the com.memetix.random.RandomNumberGenerator to all of the service methods, this just determines which one will be used should you not provide it.

Algorithms

First, you may want to choose an algorithm. The Mersenne Twister is the default used by this plugin.

  • Mersenne Twister - default

    A Java port of the fast and reliable Mersenne Twister RNG originally developed by Makoto Matsumoto and Takuji Nishimura. It is faster than java.util.Random, does not have the same statistical flaws as that RNG and also has a long period (219937). The Mersenne Twister is an excellent general purpose RNG.

    Config.groovy:

      random.generator.default="MERSENNE_TWISTER"
    
  • XOR Shift

    A Java implementation of the very fast PRNG described by George Marsaglia. It has a period of about 2160, which although much shorter than the Mersenne Twister's, is still significantly longer than that of java.util.Random. This is the RNG to use when performance is the primary concern. It can be up to twice as fast as the Mersenne Twister.

    Config.groovy:

      random.generator.default="XOR_SHIFT"
    
  • AES Counter

    This is a cryptographically-strong1 non-linear RNG that is around 10x faster than java.security.SecureRandom. Reverse-engineering the generator state from observations of its output would involve cracking the AES block cipher.

    Config.groovy:

      random.generator.default="AES_COUNTER"
    
  • Cellular Automaton

    A Java port of Tony Pasqualoni's fast Cellular Automaton RNG. It uses a 256-cell automaton to generate random values.

    Config.groovy:

      random.generator.default="CELLULAR_AUTOMATON"
    

RandomTagLib

Tags

All tags exist in the random namespace and return Objects, which means you may call them as methods from within your own controllers and taglibs . For example:

def myShuffledList = random.shuffle(list:[1,2,3,4,5,6,7,8,9,10])

nextInteger

Returns a random integer

Parameters

  • ceiling - optional upper bound of the random number range. Non-inclusive. If a ceiling is specified without a floor, the floor becomes 0.
  • floor - optional lower bound of the random number range. Inclusive.
  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Example 1:

<random:nextInteger/>

Output 1:

134925

Example 2:

<random:nextInteger ceiling="100"/>

Output 2:

92

Example 3:

<random:nextInteger ceiling="3500" floor="2500"/>

Output 3:

3317

nextLong

Returns a random long

Parameters

  • ceiling - optional upper bound of the random number range. Non-inclusive. If a ceiling is specified without a floor, the floor becomes 0.
  • floor - optional lower bound of the random number range. Inclusive.
  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Example 1:

<random:nextLong/>

Output 1:

-3462449385734449569

Example 2:

<random:nextLong ceiling="100"/>

Output 2:

77

Example 3:

<random:nextLong ceiling="-3111111111111111111" floor="-3000000000000000000"/>

Output 3:

3000005023402523523

nextBoolean

Returns a random boolean - i.e. flips a coin

Parameters

  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Example 1:

<random:nextBoolean/>

Output 1:

false

shuffle

Shuffles a list and returns the shuffled list

Parameters

  • list - a List of any type of object that you like shuffled in a random order
  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Example 1:

<random:shuffle list="${[1,2,3,4,5,6,7,8,9,10]}"/>

Output 1:

[7, 5, 1, 8, 3, 4, 6, 2, 10, 9]

draw

Draws a random object from the provided list and returns the object that was drawn

Parameters

  • list - a List of any type of object from which you would like to draw a random item
  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Example 1:

<random:draw list="${[1,2,3,4,5,6,7,8,9,10]}"/>

Output 1:

4

RandomService

Services


nextInteger

Overloads

  • nextInteger()
  • nextInteger(RandomNumberGenerator rng)
  • nextInteger(int ceiling, RandomNumberGenerator rng)
  • nextInteger(int floor, int ceiling,RandomNumberGenerator rng)

Returns the next Integer from the random number generator. Optionally provide a floor, ceiling, or specific Random Number Generator to use.

Parameters

  • ceiling - optional upper bound of the random number range. Non-inclusive. If a ceiling is specified without a floor, the floor becomes 0.
  • floor - optional lower bound of the random number range. Inclusive.
  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Returns

  • A random int

Example:

randomService?.nextInteger(400)

returns

233

Overloads

  • nextLong()
  • nextLong(RandomNumberGenerator rng)
  • nextLong(long ceiling, RandomNumberGenerator rng)
  • nextLong(long floor,long ceiling,RandomNumberGenerator rng)

Returns the next Long from the random number generator. Optionally provide a floor, ceiling, or specific Random Number Generator to use.

Parameters

  • ceiling - optional upper bound of the random number range. Non-inclusive. If a ceiling is specified without a floor, the floor becomes 0.
  • floor - optional lower bound of the random number range. Inclusive.
  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Returns

  • A random long

Example:

randomService?.nextLong()

returns

2528037343378495488

nextDouble

Overloads

  • nextDouble()
  • nextDouble(RandomNumberGenerator rng)

Returns the next Double from the random number generator. Optionally provide a specific Random Number Generator to use.

Parameters

  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Returns

  • A random double between 0.0 and 1.0

Example:

randomService?.nextDouble()

returns

0.56673834568494979785

shuffle

Overloads

  • shuffle(List list)
  • shuffle(List list, RandomNumberGenerator rng)

Randomly shuffles the elements of the provided list.

Parameters

  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Returns

  • A list that has had its contents shuffled randomly

Example:

def list = [1,2,3,4,5,6,7,8,9,10]
randomService?.shuffle(list)

returns

[2, 6, 4, 5, 7, 9, 3, 10, 1, 8]

draw

Overloads

  • draw(List list)
  • draw(List list, RandomNumberGenerator rng)

Returns a random item from the provided list

Parameters

  • generator - optional String representing the name of the Random Number Generation algorithm or an instance of com.memetix.RandomNumberGenerator

Returns

  • An element from the provided list, selected at random

Example:

def list = [1,2,3,4,5,6,7,8,9,10]
randomService?.draw(list)

returns

7

Source Code @ GitHub

The source code is available on GitHub at https://github.com/boatmeme/grails-random.

Find a bug? Fork it. Fix it. Issue a pull request.

git clone git://github.com/boatmeme/grails-random

Contributions welcome!

Issue Tracking @ GitHub

Issue tracking is also on GitHub at https://github.com/boatmeme/grails-random/issues.

Bug reports, Feature requests, and general inquiries welcome.

Contact

Feel free to contact me by email (jonathan.griggs at gmail.com) or follow me on GitHub at https://github.com/boatmeme.

Roadmap

Future versions should include:

  • Ability to reseed the PRNGs
  • Ability to specify the SeedGenerator to use (i.e. Random.org, /dev/null, and SecureRandom)
  • Services that expose the Probability Distribution Wrappers (Uniform, Normal, Binomial, Poisson and Exponential)

Change Log

v0.2 - 2012.05.15

  • Upgraded to Grails 2.0.3
  • Set transactional = false in RandomService

v0.1 - 2011.06.17

  • Initial release