You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现:无需列表的大范围内唯一随机数生成算法

在0~0xFFFFFFFF范围内生成无重复随机数(无需全量存储)

核心方案:全周期线性同余生成器(LCG)

LCG是一种轻量级伪随机数生成算法,当参数选择合适时,能遍历目标范围内的所有整数且不重复(即全周期),全程仅需维护一个当前值状态,内存占用可以忽略。针对32位无符号整数范围(0~0xFFFFFFFF),只要满足以下参数条件即可实现全周期:

  • 模数 m = 2^32(正好对应目标范围)
  • 增量 c 为奇数
  • 乘数 a 满足 a ≡ 1 mod 4

PHP实现代码

class UniqueRandom32Bit {
    private $current;
    // 经典全周期32位LCG参数,经过验证可遍历所有32位无符号整数
    private const A = 1664525;
    private const C = 1013904223;
    private const MOD = 0x100000000; // 2^32

    public function __construct() {
        // 用真随机数初始化起始值,避免每次启动生成完全相同的序列
        $this->current = random_int(0, self::MOD - 1);
    }

    public function next(): int {
        // 计算下一个值,自动循环遍历所有数
        $this->current = (self::A * $this->current + self::C) % self::MOD;
        // 确保返回32位无符号整数(兼容PHP的64位int)
        return $this->current & 0xFFFFFFFF;
    }

    // 重置序列,重新生成新的起始值
    public function reset(): void {
        $this->current = random_int(0, self::MOD - 1);
    }
}

// 使用示例
$generator = new UniqueRandom32Bit();
// 生成10个唯一随机数
for ($i = 0; $i < 10; $i++) {
    echo $generator->next() . PHP_EOL;
}
// 用完一轮后重置序列
$generator->reset();

原理说明

  • 每次调用next()时,通过LCG公式计算下一个值,由于参数满足全周期条件,会遍历0~0xFFFFFFFF的所有数,无重复,直到所有数生成完毕后自动循环。
  • 仅需存储一个32位整数状态,完全不受范围大小影响,内存占用极低。
  • 初始化和重置时用random_int()获取真随机起始值,避免固定序列,保证随机性。

替代方案:Feistel网络置换(高安全性场景)

如果需要防预测的强随机序列,可以用Feistel网络实现32位整数的置换,同样无需存储全量列表,仅维护一个计数器即可。

PHP实现代码

class FeistelUniqueRandom {
    private $counter = 0;
    private const ROUNDS = 4;
    private $key;

    public function __construct() {
        // 初始化随机密钥,避免固定置换规则
        $this->key = random_int(0, 0xFFFFFFFF);
    }

    private function feistel(int $value): int {
        $left = ($value >> 16) & 0xFFFF;
        $right = $value & 0xFFFF;

        // 多轮置换增强随机性
        for ($i = 0; $i < self::ROUNDS; $i++) {
            $temp = $right;
            // 自定义轮函数,可替换为hash函数进一步提升安全性
            $f = (($right * 0x41C64E6D) + $this->key + $i) & 0xFFFF;
            $right = $left ^ $f;
            $left = $temp;
        }

        return ($left << 16) | $right;
    }

    public function next(): int {
        $value = $this->counter++ % 0x100000000;
        return $this->feistel($value);
    }

    public function reset(): void {
        $this->counter = 0;
        // 重置时更换密钥,生成全新置换序列
        $this->key = random_int(0, 0xFFFFFFFF);
    }
}

// 使用示例
$feistelGen = new FeistelUniqueRandom();
for ($i = 0; $i < 10; $i++) {
    echo $feistelGen->next() . PHP_EOL;
}
$feistelGen->reset();

方案对比

  • LCG方案:性能极高,计算简单,适合对性能要求高、安全性要求一般的场景。
  • Feistel方案:序列随机性更强,具备防预测能力,适合敏感场景,但性能略低于LCG。

两种方案均无需存储全量数值,仅维护少量状态变量,完全满足你的需求。

内容的提问来源于stack exchange,提问作者Volker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 04:52:47