Is It Okay To Static-ify Random?

I am tired of making an object for random every time I want to do something random. Can I just make a class and use it like this:


RandomClass.nextBoolean();
// RandomClass just wraps around a Random object.

As apposed to


Random rand = new Random();
// ...
if(rand.nextBoolean())
    printCrap();

I personally wouldn’t, but yes you can do that.

Things to watch out for are:

  • threading; while Random is thread-safe, the class warns concurrent use across threads can cause contention issues.
  • determinism; if you need it, you’ll find you have to redesign your code.
  • lazy design; do this for Random, and you might find yourself static-ifying other more important stuff. [yoda quote here, relating to dark path & dominated destiny].

[quote] I decided that every time you ask for a nextFloat, or nextInt, it refreshes the seed to the millis of the day * some mumbo jumbo… Sounds like it will work.
[/quote]
You do know how the random class works right?

I personally prefer [icode]Math.random()[/icode] for the same reason as you. Some methods for you with documentation.


/**
 * Returns a random real number between 0 and x. The number is always
 * smaller than x.
 *
 * @param x The maximum range
 * @return A random real number
 */
public static int random(int x)
{
    return (int)(Math.floor(Math.random() * x));
}

/**
 * Returns a random real number between x1 (inclusive) and x2 (exclusive).
 *
 * @param x1 The inclusive
 * @param x2 The exclusive
 * @return A random real number between x1 and x2
 */
public static int random_range(int x1, int x2)
{
    return (int)(Math.floor(x1 + (Math.random() * (x2 - x1))));
}

My [icode]GUtil[/icode] class if you want more functions. You are warned that this class is older than 2 years and is used with Java2D.

If you want to use booleans, try this.


public static boolean random_boolean()
{
    return random(2) == 0;
}

Hope this helps.

You’re doing an awful lot of conversions from int->double and vice-versa there. A better implementation would be:


package renoria.util;

/**
 * Random utility... o.O!
 * @author David
 */
public final class RandomUtil {
	/**
	 * State of this object cannot be trusted, so always use this for a random number you don't care about synchronizing
	 */
    public static final MersenneTwister rand = new MersenneTwister();

    private RandomUtil() {}

    public static long choose(long... args) {
        int choice = rand.nextInt(args.length - 1);

        return args[choice];
    }

    public static double choose(double... args) {
        return args[rand.nextInt(args.length - 1)];
    }

    public static char choose(char... args) {
        return args[rand.nextInt(args.length - 1)];
    }

    public static Object chooseObject(Object... args) {
        return args[rand.nextInt(args.length - 1)];
    }

    public static int range(int lbound, int ubound) {
        return (rand.nextInt(ubound - lbound + 1)) + lbound;
    }

    public static float range(float lbound, float ubound) {
        return (rand.nextFloat() * (ubound - lbound + 1)) + lbound;
    }

    public static boolean bool() {
        return rand.nextBoolean();
    }
}


I use MersenneTwister here but you can easily just drop in java.util.Random.

The random class is seeded to the time of day since I believe 1980. Just making random static doesn’t mean it will stop seeding its numbers.

That’s a really bad idea. Random number will now be correlated which is opposite of what you want. It’s almost this:

My strong suggestion is to not use MT unless you need a supercomputer to run your program.

(EDIT: typo)

Who cares about upper bounds :slight_smile:

I use


    public static final int getRandom(int minimum, int maximum)
    {
        return (int)(Math.random()*((maximum+1)-minimum)+minimum);
    }

    public static final float getRandom(float minimum, float maximum)
    {
        return (float)(Math.random()*((maximum+1)-minimum)+minimum);
    }

first: never be afraid of static - we use it a lot. Everbody should know about best practises in programming but also realize that programming a game with a limited amount of people is different from working at a huge codebase, written to be reused in other projects and so forth.

second: on the topic of random.
the question is how good has your random got to be here ? if you just want some random movement for example, thats a different level of concern that having a droprate in a game which can directly influence a mmo’s global economy or might even be abused
but in usual cases the static way is absolutely fine
Seeds are great for testing - IF this particular part of the code will ever need test with these random values

Jan 1st, 1970 00:00:00

I answered this in a trivia competition today and I won $10 itunes card…

What am I gonna do with this pointless card? :emo: ???

Give it to me! ;D

Damn, I knew I was wrong! Fine, you win :slight_smile:

Who cares about upper bounds :slight_smile:

Seriously dudes, test your code.

@Riven

I feel like I am missing something about it?

Why are we ‘not caring about upper bounds’ ?

What if I wanted a number between 90 and 100
Sure, one could just write Math.random()*10 + 90 but they could also write getRandom(90,100) as well ? I mean I guess its not really much more or less code but with the method it seems a little more clear?

They add 1.0f. Which is barely defendable for integers, but flat out wrong for floats.

Their methods return values with the upper bound increased by 1.0:

range(0.2f, 0.5f) => returns values between 0.2f and 1.5f
getRandom(-0.3f, 1.5f) => returns values between -0.3f and 2.5f

Given this bug is so obvious, and guaranteed to return out of range values often, it’s hard to believe that:

[quote=“SHC,post:4,topic:44676”]

Hah! Brilliant ;D :stuck_out_tongue:

It worked for ints so I did it and never ever looked at it.
Sometime I needed a float one, didn’t think about it and just changed int to float, never really tested it.

[quote=“Riven,post:15,topic:44676”]
Given this bug is so obvious, and guaranteed to return out of range values often, it’s hard to believe that:

Actually older for me…
Mostly used the int one though

Should be


    public static final float getRandom(float minimum, float maximum)
    {
        return (float)(Math.random()*(maximum-minimum))+minimum;
    }

While it is implied that maximum is higher than minimum

What you were looking for was adding one ulp, to include the upper bound value in the returned range.

For integers that’s 1, for floats and doubles that’s very close to zero.

[1,1] -> mapToPMO