-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrand_number.py
125 lines (94 loc) · 2.6 KB
/
rand_number.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import math
def LCG(seed, multi, incr, mask):
"""generate a random integer by LCG
Args:
seed: seed
multi: multiplier
incr: increment
mask: modulus
Returns:
the next integer generated by LCG
"""
return (seed * multi + incr) & mask
def rand48(seed):
"""generate a random number by RAND48
Args:
seed: seed to use for LCG
Returns:
a pseudo random integer generated by rand48
"""
multi = 25214903917
incr = 11
mask = 2 ** 48 - 1
return LCG(seed, multi, incr, mask)
SeedJava = 156079716630527
def post_processing(value):
"""pass the value on 48 bits to 32 bits by deleting the 16 least significant bits
* shift right 16 bits of value
* then, if value < 0 then value += 2^32; else return value
Args:
value: the integer on 48 bits to pass to 32 bits
Returns:
an integer of 32 bits
"""
value = value >> 16
if value & 2 ** 31:
value -= 2 ** 32
return value
def generator_Java():
"""simulation of pseudo random generator in Java
Returns:
a random integer with 2^32 bits
"""
global SeedJava
res = rand48(SeedJava)
# modifying the global seed
SeedJava = res
res = post_processing(res)
return res
def reverse_java_rand48(v1, v2):
"""Giving v1 and v2 on 32 bits generated by generator_Java(), find V1 on 48 bits which
* V1's 32 most significant bits is equal to v1
* if use V1 as generator_Java()'s SeedJava, we can get v2 by generator_Java()
Args:
v1: 32 bits integer generated by generated_Java()
v2: 32 bits integer generated by generated_Java()
Returns:
the value which satisfied the 2 conditions above
"""
res = v1 << 16
while not post_processing(rand48(res)) == v2:
res += 1
return res
Index = 0
Seed = 987654321
G = rand48(Seed)
def next_bit():
"""generate pseudo randomly a 0 or 1
Returns:
0 or 1
"""
global Index, G
b = (G >> Index) % 2
Index += 1
if Index == 48:
Index = 0
G = rand48(G)
return b
def rand_int(n):
"""generate a pseudo random number between 0 and n exclusive
Args:
n: the exclusive greater border of range
Returns: (random number, number of rejects)
* the pseudo number generated
* the number of rejections
"""
nb_bits = math.ceil(math.log(n + 1, 2))
r = n + 1
rejects = -1
while r >= n:
r = 0
rejects += 1
for _ in range(nb_bits):
r = r * 2 + next_bit()
return r, (rejects + 1) * nb_bits