0
# Random Numbers
1
2
gmpy2 provides comprehensive random number generation capabilities for all multiple-precision types. The random number system uses configurable random state objects and provides various distributions suitable for cryptographic, statistical, and mathematical applications.
3
4
## Capabilities
5
6
### Random State Management
7
8
Random state objects manage the internal state of random number generators, enabling reproducible sequences and parallel random number generation.
9
10
```python { .api }
11
class random_state:
12
def __init__(self, seed=0):
13
"""
14
Create a random number generator state.
15
16
Args:
17
seed: Seed value for initialization (int, default 0)
18
19
Note:
20
Different seeds produce different random sequences
21
Same seed produces identical sequences (reproducible)
22
"""
23
```
24
25
### Integer Random Numbers
26
27
Functions for generating random integers with various distributions.
28
29
```python { .api }
30
def mpz_random(state, n):
31
"""
32
Generate random integer in range [0, n).
33
34
Args:
35
state: random_state object
36
n: Upper bound (exclusive, must be positive)
37
38
Returns:
39
mpz: Random integer 0 <= result < n
40
41
Note:
42
Uniform distribution over the specified range
43
"""
44
45
def mpz_urandomb(state, n):
46
"""
47
Generate random integer with exactly n random bits.
48
49
Args:
50
state: random_state object
51
n: Number of random bits (non-negative integer)
52
53
Returns:
54
mpz: Random integer in range [0, 2^n)
55
56
Note:
57
Each bit is independently random with probability 1/2
58
"""
59
60
def mpz_rrandomb(state, n):
61
"""
62
Generate random integer with at most n bits, different distribution.
63
64
Args:
65
state: random_state object
66
n: Maximum number of bits
67
68
Returns:
69
mpz: Random integer with different bit distribution than urandomb
70
71
Note:
72
Provides different statistical properties than urandomb
73
"""
74
```
75
76
### Floating-Point Random Numbers
77
78
Functions for generating random floating-point numbers with various precisions and distributions.
79
80
```python { .api }
81
def mpfr_random(state):
82
"""
83
Generate random float in [0, 1) with current precision.
84
85
Args:
86
state: random_state object
87
88
Returns:
89
mpfr: Random float 0 <= result < 1
90
91
Note:
92
Uses current context precision for result
93
Uniform distribution over [0, 1)
94
"""
95
96
def mpfr_grandom(state):
97
"""
98
Generate pair of Gaussian random numbers (Box-Muller method).
99
100
Args:
101
state: random_state object
102
103
Returns:
104
tuple: (x, y) where both are normally distributed mpfr values
105
106
Note:
107
Standard normal distribution (mean=0, variance=1)
108
More efficient than generating two separate normal values
109
"""
110
111
def mpfr_nrandom(state):
112
"""
113
Generate single normal (Gaussian) random number.
114
115
Args:
116
state: random_state object
117
118
Returns:
119
mpfr: Normally distributed random float
120
121
Note:
122
Standard normal distribution (mean=0, variance=1)
123
Uses current context precision
124
"""
125
```
126
127
### Complex Random Numbers
128
129
Function for generating random complex numbers.
130
131
```python { .api }
132
def mpc_random(state):
133
"""
134
Generate random complex number.
135
136
Args:
137
state: random_state object
138
139
Returns:
140
mpc: Complex number with random real and imaginary parts
141
142
Note:
143
Both real and imaginary parts are uniform in [0, 1)
144
Uses current context precision for both parts
145
"""
146
```
147
148
## Usage Examples
149
150
### Basic Random Number Generation
151
152
```python
153
import gmpy2
154
155
# Create random state with seed for reproducibility
156
rstate = gmpy2.random_state(12345)
157
158
# Generate random integers
159
print("Random integers:")
160
for i in range(5):
161
# Random integer in range [0, 1000)
162
rand_int = gmpy2.mpz_random(rstate, 1000)
163
print(f" Random [0, 1000): {rand_int}")
164
165
# Generate random integers with specific bit lengths
166
print("\nRandom integers with specific bit lengths:")
167
for bits in [8, 16, 32]:
168
rand_bits = gmpy2.mpz_urandomb(rstate, bits)
169
print(f" {bits:2d} bits: {rand_bits} (hex: {hex(rand_bits)})")
170
```
171
172
### Reproducible Random Sequences
173
174
```python
175
import gmpy2
176
177
def generate_sequence(seed, count=5):
178
"""Generate a sequence of random numbers with given seed."""
179
rstate = gmpy2.random_state(seed)
180
sequence = []
181
for _ in range(count):
182
sequence.append(gmpy2.mpz_random(rstate, 100))
183
return sequence
184
185
# Same seed produces identical sequences
186
seed = 42
187
seq1 = generate_sequence(seed)
188
seq2 = generate_sequence(seed)
189
190
print(f"Sequence 1 (seed {seed}): {seq1}")
191
print(f"Sequence 2 (seed {seed}): {seq2}")
192
print(f"Sequences identical: {seq1 == seq2}")
193
194
# Different seed produces different sequence
195
seq3 = generate_sequence(seed + 1)
196
print(f"Sequence 3 (seed {seed + 1}): {seq3}")
197
print(f"Different from seq1: {seq1 != seq3}")
198
```
199
200
### High-Precision Random Floating-Point Numbers
201
202
```python
203
import gmpy2
204
205
# Generate random floats at different precisions
206
rstate = gmpy2.random_state(98765)
207
208
precisions = [24, 53, 100, 200]
209
print("Random floats at different precisions:")
210
211
for prec in precisions:
212
with gmpy2.local_context(precision=prec):
213
rand_float = gmpy2.mpfr_random(rstate)
214
print(f" {prec:3d} bits: {rand_float}")
215
216
# Generate multiple random floats
217
print("\nMultiple random floats (53-bit precision):")
218
with gmpy2.local_context(precision=53):
219
for i in range(5):
220
rand_float = gmpy2.mpfr_random(rstate)
221
print(f" Random [0, 1): {rand_float}")
222
```
223
224
### Gaussian (Normal) Random Numbers
225
226
```python
227
import gmpy2
228
229
rstate = gmpy2.random_state(54321)
230
231
# Generate individual normal random numbers
232
print("Individual normal random numbers:")
233
with gmpy2.local_context(precision=80):
234
for i in range(5):
235
normal = gmpy2.mpfr_nrandom(rstate)
236
print(f" N(0,1): {normal}")
237
238
# Generate pairs of normal random numbers (more efficient)
239
print("\nPairs of normal random numbers:")
240
with gmpy2.local_context(precision=80):
241
for i in range(3):
242
x, y = gmpy2.mpfr_grandom(rstate)
243
print(f" Pair {i+1}: ({x}, {y})")
244
```
245
246
### Complex Random Numbers
247
248
```python
249
import gmpy2
250
251
rstate = gmpy2.random_state(11111)
252
253
print("Random complex numbers:")
254
with gmpy2.local_context(precision=60):
255
for i in range(5):
256
rand_complex = gmpy2.mpc_random(rstate)
257
print(f" Complex: {rand_complex}")
258
print(f" Magnitude: {gmpy2.abs(rand_complex)}")
259
print(f" Phase: {gmpy2.phase(rand_complex)}")
260
```
261
262
### Statistical Analysis
263
264
```python
265
import gmpy2
266
267
def analyze_random_bits(state, bit_length, count=1000):
268
"""Analyze distribution of random bits."""
269
bit_counts = [0] * bit_length
270
271
for _ in range(count):
272
rand_num = gmpy2.mpz_urandomb(state, bit_length)
273
for bit_pos in range(bit_length):
274
if gmpy2.bit_test(rand_num, bit_pos):
275
bit_counts[bit_pos] += 1
276
277
return bit_counts
278
279
# Analyze 8-bit random numbers
280
rstate = gmpy2.random_state(99999)
281
bit_analysis = analyze_random_bits(rstate, 8, 10000)
282
283
print("Bit position analysis (8-bit random numbers, 10000 samples):")
284
for pos, count in enumerate(bit_analysis):
285
percentage = (count / 10000) * 100
286
print(f" Bit {pos}: {count:4d} set ({percentage:5.1f}%)")
287
288
# Should be approximately 50% for each bit position
289
```
290
291
### Cryptographic Random Numbers
292
293
```python
294
import gmpy2
295
296
def generate_large_random_prime_candidate(bits, rstate):
297
"""Generate a large random odd number (prime candidate)."""
298
# Generate random number with specified bits
299
candidate = gmpy2.mpz_urandomb(rstate, bits)
300
301
# Ensure it's odd (required for prime)
302
candidate = gmpy2.bit_set(candidate, 0)
303
304
# Ensure high bit is set (full bit length)
305
candidate = gmpy2.bit_set(candidate, bits - 1)
306
307
return candidate
308
309
# Generate potential cryptographic prime candidates
310
rstate = gmpy2.random_state(12345678)
311
312
print("Large prime candidates for cryptographic use:")
313
for key_size in [512, 1024, 2048]:
314
candidate = generate_large_random_prime_candidate(key_size, rstate)
315
316
# Quick primality check
317
is_prime = gmpy2.is_prime(candidate, 25)
318
319
print(f"\n{key_size}-bit candidate:")
320
print(f" Hex: {hex(candidate)[:50]}...")
321
print(f" Bit length: {gmpy2.bit_length(candidate)}")
322
print(f" Is prime: {is_prime}")
323
324
if is_prime:
325
print(f" Found prime!")
326
break # In practice, you'd save this prime
327
```
328
329
### Random Range Operations
330
331
```python
332
import gmpy2
333
334
def random_in_range(state, min_val, max_val):
335
"""Generate random number in specific range [min_val, max_val]."""
336
if min_val >= max_val:
337
raise ValueError("min_val must be less than max_val")
338
339
range_size = max_val - min_val + 1
340
return gmpy2.mpz_random(state, range_size) + min_val
341
342
# Generate random numbers in custom ranges
343
rstate = gmpy2.random_state(777)
344
345
ranges = [
346
(100, 200), # Small range
347
(1000, 9999), # 4-digit numbers
348
(2**30, 2**31), # Large range
349
]
350
351
print("Random numbers in custom ranges:")
352
for min_val, max_val in ranges:
353
for _ in range(3):
354
rand_val = random_in_range(rstate, min_val, max_val)
355
print(f" [{min_val}, {max_val}]: {rand_val}")
356
```
357
358
### Monte Carlo Simulation
359
360
```python
361
import gmpy2
362
363
def estimate_pi_monte_carlo(n_points, precision=100):
364
"""Estimate π using Monte Carlo method with high precision."""
365
rstate = gmpy2.random_state(314159)
366
inside_circle = 0
367
368
with gmpy2.local_context(precision=precision):
369
for _ in range(n_points):
370
# Generate point in unit square [0,1) × [0,1)
371
x = gmpy2.mpfr_random(rstate)
372
y = gmpy2.mpfr_random(rstate)
373
374
# Check if point is inside unit circle
375
if x*x + y*y < 1:
376
inside_circle += 1
377
378
# Estimate π = 4 × (points inside circle) / (total points)
379
pi_estimate = 4 * gmpy2.mpfr(inside_circle) / n_points
380
return pi_estimate
381
382
# Estimate π with different sample sizes
383
print("Monte Carlo estimation of π:")
384
for n in [1000, 10000, 100000]:
385
pi_est = estimate_pi_monte_carlo(n, precision=80)
386
actual_pi = gmpy2.const_pi(precision=80)
387
error = abs(pi_est - actual_pi)
388
389
print(f" {n:6d} points: {pi_est}")
390
print(f" Error: {error}")
391
```
392
393
### Parallel Random Number Generation
394
395
```python
396
import gmpy2
397
398
def create_independent_generators(master_seed, count):
399
"""Create multiple independent random number generators."""
400
generators = []
401
402
# Use master generator to create seeds for independent generators
403
master_rstate = gmpy2.random_state(master_seed)
404
405
for i in range(count):
406
# Generate a unique seed for each generator
407
seed = gmpy2.mpz_random(master_rstate, 2**32)
408
generators.append(gmpy2.random_state(int(seed)))
409
410
return generators
411
412
# Create independent generators for parallel use
413
generators = create_independent_generators(123456, 4)
414
415
print("Independent random number generators:")
416
for i, gen in enumerate(generators):
417
sequence = []
418
for _ in range(5):
419
sequence.append(gmpy2.mpz_random(gen, 1000))
420
print(f" Generator {i}: {sequence}")
421
422
# Verify independence (sequences should be different)
423
all_sequences = []
424
for gen in generators:
425
seq = [gmpy2.mpz_random(gen, 100) for _ in range(10)]
426
all_sequences.append(seq)
427
428
print(f"\nAll sequences different: {len(set(map(tuple, all_sequences))) == len(all_sequences)}")
429
```