EN
Java - own random number generator (custom implementation)
14 points
In java we can implement custom random number generator by using LCG (Linear congruential generator) algorithm. LCG is one of the oldest and best-known pseudorandom number generator algorithm. We can adjust this implementation to work on int or long.
Linear congruential generator is defined by recurrence relation:
Where:
- Xn+1 - new seed
- a - MULTIPLIER_A
- Xn - current seed field
- c - INCREMENT_C
- m - MODULUS
In our below implementation above variables were used.
Note:
Every time
randomNumber()
method is called, we assign new value to seed.
xxxxxxxxxx
1
/**
2
* Based on long as int can overflow.
3
*/
4
public class RandomUtil {
5
6
private final static long MULTIPLIER_A = 1103515245L;
7
private final static long INCREMENT_C = 12345L;
8
private final static long MODULUS = 2147483647L; // max int
9
10
private static long seed = 3819201L;
11
12
public static long randomNumber() {
13
// we use long instead of int, as int can overflow
14
// when seed * MULTIPLIER_A + INCREMENT_C
15
seed = (seed * MULTIPLIER_A + INCREMENT_C) % MODULUS;
16
return seed;
17
}
18
19
public static long randomPositiveNumber() {
20
long tmp = randomNumber();
21
if (tmp < 0) {
22
seed = tmp * -1;
23
}
24
return seed;
25
}
26
27
public static void main(String[] args) {
28
System.out.println(randomPositiveNumber()); // 1801118106
29
System.out.println(randomPositiveNumber()); // 41211189
30
System.out.println(randomPositiveNumber()); // 11738570
31
32
for (int i = 0; i < 7; i++) {
33
System.out.println(randomPositiveNumber());
34
}
35
}
36
}
Output:
xxxxxxxxxx
1
1801118106
2
41211189
3
11738570
4
865299259
5
887958952
6
992620351
7
1793753076
8
477297891
9
1620379360
10
1194566247
Below 2 fields:
xxxxxxxxxx
1
long MULTIPLIER_A = 1103515245L;
2
long INCREMENT_C = 12345L;
are used by runtime libraries of various compilers:
- glibc (used by GCC)
- ANSI C: Watcom, Digital Mars, CodeWarrior, IBM VisualAge C/C++
- C90, C99, C11: Suggestion in the ISO/IEC 9899, C18
xxxxxxxxxx
1
import java.util.Arrays;
2
3
public class RandomUtilProbabilityTest {
4
5
public static void main(String[] args) {
6
int[] probabilityDistribution = new int[10];
7
8
for (int i = 0; i < 30_000; i++) {
9
long next = RandomUtil.randomPositiveNumber() % 10L;
10
probabilityDistribution[(int) next]++;
11
}
12
13
// [2979, 3049, 3000, 2971, 2975, 2954, 3016, 3072, 3027, 2957]
14
System.out.println(Arrays.toString(probabilityDistribution));
15
16
// 30000
17
System.out.println(Arrays.stream(probabilityDistribution).sum());
18
19
int min = Integer.MAX_VALUE;
20
int max = Integer.MIN_VALUE;
21
22
for (int i = 0; i < probabilityDistribution.length; i++) {
23
int next = probabilityDistribution[i];
24
min = Math.min(min, next);
25
max = Math.max(max, next);
26
}
27
28
System.out.println(" min: " + min); // min: 2954
29
System.out.println(" max: " + max); // max: 3072
30
System.out.println("diff: " + (max - min)); // diff: 118
31
}
32
}
Output:
xxxxxxxxxx
1
[2979, 3049, 3000, 2971, 2975, 2954, 3016, 3072, 3027, 2957]
2
30000
3
min: 2954
4
max: 3072
5
diff: 118
xxxxxxxxxx
1
import java.util.Arrays;
2
import java.util.Random;
3
4
public class JdkRandomProbabilityTest {
5
6
private static final Random random = new Random(3819201);
7
8
public static int nextInt(int min, int max) {
9
return random.nextInt((max - min) + 1) + min;
10
}
11
12
public static void main(String[] args) {
13
int[] probabilityDistribution = new int[10];
14
15
for (int i = 0; i < 30_000; i++) {
16
int next = nextInt(0, Integer.MAX_VALUE - 1) % 10;
17
probabilityDistribution[next]++;
18
}
19
20
// [2963, 2885, 3049, 3041, 3002, 3089, 2967, 3020, 3019, 2965]
21
System.out.println(Arrays.toString(probabilityDistribution));
22
23
int min = Integer.MAX_VALUE;
24
int max = Integer.MIN_VALUE;
25
26
for (int i = 0; i < probabilityDistribution.length; i++) {
27
int next = probabilityDistribution[i];
28
min = Math.min(min, next);
29
max = Math.max(max, next);
30
}
31
32
System.out.println(" min: " + min); // min: 2903
33
System.out.println(" max: " + max); // max: 3093
34
System.out.println("diff: " + (max - min)); // diff: 190
35
}
36
}
Output:
xxxxxxxxxx
1
[2976, 2984, 3091, 3093, 3037, 2969, 3030, 2903, 2905, 3012]
2
min: 2903
3
max: 3093
4
diff: 190