随机数生成完全指南:伪随机 vs 真随机
随机数在编程中有广泛应用。本文介绍随机数生成的原理和方法。
伪随机 vs 真随机
伪随机数(PRNG)
基于算法生成,可预测。
// 伪随机:种子相同,结果相同
Math.random(); // 0.7234...
特点:
- 速度快
- 可重复(相同种子)
- 不适合安全场景
真随机数(TRNG)
基于物理现象生成,不可预测。
硬件噪声
放射性衰变
大气噪声
特点:
- 不可预测
- 不可重复
- 适合安全场景
各语言随机数生成
JavaScript
// 伪随机
Math.random(); // 0-1 之间
// 安全随机
crypto.getRandomValues(new Uint32Array(1))[0];
crypto.randomUUID(); // UUID
Java
// 伪随机
new Random().nextInt(100);
// 安全随机
new SecureRandom().nextInt(100);
// ThreadLocalRandom(多线程)
ThreadLocalRandom.current().nextInt(100);
Python
import random
import secrets
# 伪随机
random.randint(1, 100)
# 安全随机
secrets.randbelow(100)
secrets.token_hex(16)
随机数应用场景
1. 游戏
// 骰子
const dice = Math.floor(Math.random() * 6) + 1;
// 洗牌
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
2. 抽奖
function draw(winners, count) {
const shuffled = shuffle([...winners]);
return shuffled.slice(0, count);
}
3. 密码生成
function generatePassword(length) {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const array = new Uint32Array(length);
crypto.getRandomValues(array);
return Array.from(array, x => chars[x % chars.length]).join('');
}
4. UUID 生成
crypto.randomUUID();
// '36b8f84d-df4e-4d49-b662-bcde71a8764f'
随机数质量测试
频率测试
检查每个数字出现的频率是否均匀。
序列测试
检查连续数字的模式是否随机。
熵值测试
计算随机数的熵值,评估随机性。
在线工具
使用 jsjson.com 随机数生成工具 生成随机数:
- 整数范围
- 小数精度
- 批量生成
- 安全随机
最佳实践
- 安全场景使用 SecureRandom:密码、令牌、密钥
- 游戏场景使用伪随机:性能优先
- 测试场景使用固定种子:可重复
- 避免自己实现随机算法:使用标准库
总结
选择随机数生成方式时,需要考虑安全性和性能的平衡。安全场景使用加密级随机数,其他场景使用伪随机数即可。