【问题标题】:I need a portable, consistent pseudorandom number generator我需要一个便携的、一致的伪随机数生成器
【发布时间】:2009-03-27 14:07:28
【问题描述】:

我正在编写一个 kid sister encryption 函数,我需要一个 PRNG,它可以在整个操作系统中产生一致的结果(因此没有浮点数学,利用硬件或系统级软件)。这会很好,但没必要,因为 PRNG 的周期长于 230

我目前使用的是 32 位的Xorshift

#!/usr/bin/perl

use strict;
use warnings;

{
    use integer; #use integer math
    my $x = 123456789;
    my $y = 362436069;
    my $w = 88675123; 
    my $z = 521288629;

    sub set_random_seed {
        $w = shift;
    }

    sub random { 
        my $t = $x ^ ($x << 11);
        $x = $y;
        $y = $z;
        $z = $w;
        my $rand = $w = ($w ^ ($w >> 19)) ^ ($t ^ ($t >> 8)); 
        return $rand % 256; #scale it back to a byte at a time
    }
}

set_random_seed(5);
print map { random(), "\n" } 1 .. 10;

但我很担心,因为我真的不明白它是如何工作的。例如,原始来源没有设置种子的能力,所以我添加了一个,但我不知道我是否为种子选择了正确的变量。

所以,所有这些都归结为

  1. 您知道 CPAN 上有一个模块可以满足我的需求吗?
  2. 如果没有,您知道适合我需要的算法吗?

【问题讨论】:

    标签: perl prng


    【解决方案1】:

    Math::Random::Auto 是一个 CPAN 模块,实现了众所周知的 Mersenne twister PRNG。

    【讨论】:

    • 但是一致吗?如果我用 5 播种它,它会在 Linux、BSD、OS X、Win32 等上产生相同的结果吗?
    • 如果您阅读该 Wikipedia 链接,您会注意到它在“应用程序”下的第一句话是它不适合密码学。
    • @cjm:如果您阅读了那个小姐姐加密链接,您会发现这可能不相关。
    • 是的,我使用的算法确实不比ROT13强。它的存在是为了给不知道更好的人一种温暖的模糊感觉。我更担心便携性。
    【解决方案2】:

    尝试使用 LFSR - Linear Feedback Shift Register.。外部链接上的 The first link 拥有产生任意位数随机性所需的一切。这样做的好处是它很容易实现,并且可以使用所有整数数学来完成。

    我在一个 8051 项目中成功使用了它。使用 perl 将是一件轻而易举的事。

    更新:

    这是一个 8 位 LFSR 的快速 perl 实现:

    use strict;
    use warnings;
    
    use List::Util qw(reduce);
    use vars qw($a $b);
    
    print 'Taps: ', set_taps( 8, 7, 2, 1 ), "\n";
    print 'Seed: ', seed_lfsr( 1 ), "\n";
    print read_lfsr(), "\n" for 1..10;
    
    BEGIN {
        my $tap_mask;
        my $lfsr = 0;
    
        sub read_lfsr {
            $lfsr = ($lfsr >> 1) ^ (-($lfsr & 1) & $tap_mask );
    
            return $lfsr;
        }
    
        sub seed_lfsr {
            $lfsr = shift || 0;
            $lfsr &= 0xFF;
        }
    
        sub set_taps {
            my @taps = @_;
    
            $tap_mask = reduce { $a + 2**$b } 0, @taps;
    
            $tap_mask >>= 1;
    
            $tap_mask &= 0xFF;
    
            return $tap_mask;
        }
    }
    

    这段代码只是一个原型。如果我想在生产中使用它,我可能会将它包装在一个对象中并使寄存器大小可配置。然后我们就可以摆脱那些讨厌的共享变量了。

    【讨论】:

    • 点击进入 wiki 会显示一系列迷人的功能。这很整洁。
    猜你喜欢
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 2014-01-20
    • 2012-09-02
    • 2023-01-03
    相关资源
    最近更新 更多