# Thread: A superiour random utility

1. I'm tired of seeing redundant and incorrect use of random utilies and incorrect probability. I vowed to release something better and that's what I'm doing today. Please delete Misc.getRandom after reading.

What's the problem?
• Manually manipulating random generator methods to reach the target domain. This bloats code and isn't readable. Leaves possibility of errors. One notable error I saw was choosing a random array element that had a chance of an array index out of bounds. int id = rewardIds[Misc.getRandom(rewardIds.length)] was something like that.
• Incorrect or unclear probabilities. If Misc.getRandom(100) == 1. Looks like a 1/100 chance, on most servers it is 1/101. I've seen too much probabilities that were clearly intended to be a round value but were off by one.
• Lack of available methods. This is the reason of the first point above.
• Concentrating on easily abstracted things.

Examples of use
Code:
``````if (Rand.hit(6)) {
// 1/6 chance to get here
}``````
Code:
``````if (Rand.hitPercent(50)) {
// 50% chance to get here
}``````
Code:
``````if (Rand.hitProbability(0.6)) {
// probability of 0.6 to get here
}``````
Code:
``````int[] ids = new int[] {4151, 6585, 2347, 1263};
int randomId = Rand.randElement(ids);``````
Code:
``boolean tails = Rand.nextBoolean();``
Code:
``int coinsAmount = Rand.inclusive(5_000_000, 25_000_000);``
Todo
I never really finished this and plan to later. I still want to add parameter validation / error handling. I also want to add a method for chosing k distinct elements from a collection of size n in O(k) time using Fisher-Yates. And a method for choosing a random element but excluding a certain index (e.g. How wilderness oblisks work, you teleport to a different oblisk than your current one). I might add support for other collections but I honestly can't see much cases for it. This is still a huge improvement from the existing random utilities and people should switch if you still use ones from pi, elvarg, ruse, maybe Vencillio and whatever else. This isn't rocket science code, I just don't want to see the next released sources with the same shit.

Make a new class called Rand.java and copy this into it.
Code:
``````import java.security.SecureRandom;
import java.util.List;

/**
* Used for random generation of numbers for probability events and random selection.
*
* @author Patrick/!knd6060#4741
*/
public class Rand {
private static final SecureRandom gen = new SecureRandom();

/**
* Random generator for hitting a certain probability.
*
*    @[Only registered and activated users can see links. ] denom The 1/denom chance that this returns true.
*    @[Only registered and activated users can see links. ] Whether the chance was hit.
*/
public static boolean hit(int denom) {
return gen.nextInt(denom) == 0;
}

/**
* Random generator for hitting a certain probability.
*
*    @[Only registered and activated users can see links. ] percent The percent rate that this returns true.
*    @[Only registered and activated users can see links. ] Whether the percent was hit.
*/
public static boolean hitPercent(int percent) {
return gen.nextInt(100) < percent;
}

/**
* Random generator for hitting a certain probability.
*
*    @[Only registered and activated users can see links. ] p The probability of success / the probability that this returns true. p must be between 0 and 1 inclusive.
*    @[Only registered and activated users can see links. ] Whether the probability was hit.
*/
public static boolean hitProbability(double p) {
return gen.nextDouble() < p;
}

/**
* Returns a random element of a generic list.
*
*    @[Only registered and activated users can see links. ] list
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static <T> T randElement(List<T> list) {
return list.get(gen.nextInt(list.size()));
}

/**
* Returns a random element of a generic array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static <T> T randElement(T[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a int[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static int randElement(int[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a boolean[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static boolean randElement(boolean[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a double[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static double randElement(double[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a byte[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static byte randElement(byte[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a char[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static char randElement(char[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a float[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static float randElement(float[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a short[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static short randElement(short[] array) {
return array[gen.nextInt(array.length)];
}

/**
* Returns a random element of a long[] array.
*
*    @[Only registered and activated users can see links. ] array
*    @[Only registered and activated users can see links. ] random element from the array
*/
public static long randElement(long[] array) {
return array[gen.nextInt(array.length)];
}

public static int inclusive(int low, int high) {
return low + gen.nextInt(high - low + 1);
}

public static boolean nextBoolean() {
return gen.nextBoolean();
}

/**
*
*    @[Only registered and activated users can see links. ] bound
*    @[Only registered and activated users can see links. ] random number between 0 inclusive and bound exclusive
*/
public static int nextInt(int bound) {
return gen.nextInt(bound);
}

/**
*
*    @[Only registered and activated users can see links. ] bound
*    @[Only registered and activated users can see links. ] random number between 0 inclusive and bound inclusive
*/
public static int nextInclusiveInt(int bound) {
return gen.nextInt(bound + 1);
}

public static double nextDouble() {
return gen.nextDouble();
}

public static double nextFloat() {
return gen.nextFloat();
}
}``````
Note: there's an important reason why I decided not to provide a nextLong() method. The seed size (48 bits) for the random generator is less than 64 bits so it is impossible to generate all possible long values and you would have statistically inconsistent randomness. Very rare that you would even need such a method.

Note2: You can use ThreadLocalRandom instead of SecureRandom if you have an application with high concurrent usage of this class at the cost of losing cryptographic security of the prng.

2. bump

3. Not super familiar with Java, aren't the overloads for the arrays of primitives unnecessary since you have the generic T[] overload?
And I think you could use Iterable<T> instead of List<T>, so you can support Set, Queue etc?

4. ## Thankful user:

5. Originally Posted by testicles
Not super familiar with Java, aren't the overloads for the arrays of primitives unnecessary since you have the generic T[] overload?
And I think you could use Iterable<T> instead of List<T>, so you can support Set, Queue etc?
Java doesn't support primitive generics (yet)

6. ## Thankful user:

7. Originally Posted by testicles
Not super familiar with Java, aren't the overloads for the arrays of primitives unnecessary since you have the generic T[] overload?
And I think you could use Iterable<T> instead of List<T>, so you can support Set, Queue etc?
I will look into this thanks! I dont see when it would be used and i was a bit fishy about sets since the order isnt usually preserved but it might not matter anyway, as long as you have access to the size and can grab elements at a specified index it can work. However a random element from a queue shouldnt be done, that violates the data structures and wont be required. Also this class must bot leave any side effects, so no modifying of objects. I'll look into some other daa structures though, set especially.

Edit: iterable doesn't have a method for getting the size. I can loop over everything once to get the size and then iterate to the required element and return it though, I'll add this later. I guess queues will be added along with it then lol

8. Originally Posted by knd6060
I will look into this thanks! I dont see when it would be used and i was a bit fishy about sets since the order isnt usually preserved but it might not matter anyway, as long as you have access to the size and can grab elements at a specified index it can work. However a random element from a queue shouldnt be done, that violates the data structures and wont be required. Also this class must bot leave any side effects, so no modifying of objects. I'll look into some other daa structures though, set especially.

Edit: iterable doesn't have a method for getting the size. I can loop over everything once to get the size and then iterate to the required element and return it though, I'll add this later
Keep in mind if a method accepts an Iterable, that it can be called using a Queue, so maybe not a good idea after all. If you really don't want your random methods to be used with queues, it's better to enforce a more concrete type than to say "this method takes an Iterable, oops you tried to use a Queue that's not allowed" and then (most likely) throw an exception.
Looks like I'm a bit spoiled by C# syntactic sugar and LINQ

The way I've approached this in C# for my server:

Code:
``````private static T GetRandomElement<T>(IReadOnlyCollection<T> thing)
{
return thing.ElementAt(SomeRandom.Next(0, thing.Count));
}``````
But as Corey mentioned Java doesn't yet have support for generic collections of primitives, this will work with any collection that implements IReadOnlyCollection and the compiler assures immutability. This works for the ones you'd commonly use, like lists and arrays.

Code:
``````static void Main(string[] args)
{
var intList = new List<int> { 1, 33, 96, 4 };
Console.WriteLine(GetRandomElement(intList));

var intArray = new[] { 2, 99, 123, 456 };
Console.WriteLine(GetRandomElement(intArray));

var queue = new Queue<int>();
queue.Enqueue(36);
queue.Enqueue(594);
queue.Enqueue(672);
queue.Enqueue(3);

Console.WriteLine(GetRandomElement(queue));

}``````
Alternatively you can be less specific and do this, IEnumerable I believe is the closest interface to Java's Iterable.
Code:
``````private static T GetRandomElement<T>(IEnumerable<T> thing)
{
var thingArray = thing.ToArray(); // I love LINQ. This gives a good explanation of why you'd do this here https://stackoverflow.com/questions/8240844/handling-warning-for-possible-multiple-enumeration-of-ienumerable
return thingArray[SomeRandom.Next(0, thingArray.Length)];
}``````

9. Originally Posted by knd6060
I will look into this thanks! I dont see when it would be used and i was a bit fishy about sets since the order isnt usually preserved but it might not matter anyway, as long as you have access to the size and can grab elements at a specified index it can work. However a random element from a queue shouldnt be done, that violates the data structures and wont be required. Also this class must bot leave any side effects, so no modifying of objects. I'll look into some other daa structures though, set especially.

Edit: iterable doesn't have a method for getting the size. I can loop over everything once to get the size and then iterate to the required element and return it though, I'll add this later. I guess queues will be added along with it then lol

10. Thanks for responses I'll look into them and learn about it in a bit. I dont care too much about the queues working, if user wants random wueue whatever it is possible and not an issue just a bit weird. Although how much error handling should be done in general? I feel like catching a bunch of illegal argument exception would be a pain. For Rand.hitProbability it isnt an issue if it is passed like 1.2 it will just always return true and means clamping of probability doesnt need to be done elsewhere. Negative values woul cause an error but I could return false for negatve probabilities rather than throwing a error, thoughts on this?

Originally Posted by Kris
What was the reason for this? Collection does have a size() method but not a get method at index. So would still need to iterate to return. I Might have missed the point. Also Queue is still in collection but idc about queue that much anymore.