Domanda

Sto scrivendo un crittografia sorellina funzione e la ho bisogno di un PRNG che produce risultati coerenti tra sistemi operativi (in modo che nessun matematiche in virgola mobile, sfruttando l'hardware o il software a livello di sistema). Sarebbe bello, ma non necessario, per il PRNG ha avuto un periodo più lungo di 2 30 .

Attualmente sto usando un 32 bit 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;

Ma io sono preoccupato perché io non capisco come funziona. Ad esempio, la fonte originale non ha avuto la capacità di impostare il seme, così ho aggiunto una, ma non so se ho scelto la variabile corretta per il seme.

Quindi, tutto questo si riduce a

  1. Sei a conoscenza di un modulo su CPAN che si adatta alle mie esigenze?
  2. In caso contrario, sai di un algoritmo che si adatta alle mie esigenze?
È stato utile?

Soluzione

Math :: :: Auto a caso è un modulo CPAN attuando il noto Mersenne twister PRNG.

Altri suggerimenti

Prova ad utilizzare un LFSR - Commenti lineare Shift Register .. T lui primo link sui link esterni ha tutto il necessario per la produzione di un numero qualsiasi di bit di casualità. La cosa bella di questo è che è facile da implementare e può essere fatto utilizzando tutti matematica intero.

L'ho usato con successo su un progetto 8051. Con perl sarà un gioco da ragazzi.

Aggiornamento:

Ecco un'implementazione perl rapida di un LFSR 8 bit:

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;
    }
}

Questo codice è solo un prototipo. Se avessi voluto utilizzare in produzione probabilmente sarei avvolgerla in un oggetto e fare il formato registro configurabile. Poi saremmo sbarazzati di queste variabili condivise fastidiosi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top