我需要一个便携,一致的伪随机数生成器

时间:2009-03-27 14:07:29

标签: perl prng

我正在编写一个kid sister encryption函数,我需要一个PRNG,它可以在OS上产生一致的结果(所以没有浮点数学,利用硬件或系统级软件)。如果PRNG的周期长于2 30 ,那将是很好的,但不是必要的。

我目前正在使用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. 如果没有,您知道哪种算法符合我的需求吗?

2 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:7)

尝试使用LFSR - Linear Feedback Shift Register.。外部链接上的T he 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;
    }
}

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