أحتاج إلى مولد أرقام عشوائية زائفة محمول ومتسق

StackOverflow https://stackoverflow.com/questions/689889

  •  22-08-2019
  •  | 
  •  

سؤال

أنا أكتب أ تشفير أخت الطفل وظيفة وأحتاج إلى 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. إذا لم يكن الأمر كذلك، هل تعرف خوارزمية تناسب احتياجاتي؟
هل كانت مفيدة؟

المحلول

الرياضيات::عشوائي::تلقائي هي وحدة CPAN تنفذ ما هو معروف إعصار ميرسين برنج.

نصائح أخرى

حاول استخدام LFSR - سجل إزاحة التغذية المرتدة الخطية.هو الرابط الأول على الروابط الخارجية يحتوي على كل ما تحتاجه لإنتاج أي عدد من البتات العشوائية.والشيء الجميل في هذا هو أنه سهل التنفيذ ويمكن القيام به باستخدام جميع الرياضيات الصحيحة.

لقد استخدمته بنجاح في مشروع 8051.مع بيرل سيكون الأمر سهلاً.

تحديث:

فيما يلي تنفيذ سريع لـ Perl لـ LFSR 8 بت:

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

هذا الرمز هو مجرد نموذج أولي.إذا كنت أرغب في استخدامه في الإنتاج، فربما أقوم بتغليفه في كائن وجعل حجم التسجيل قابلاً للتكوين.ومن ثم سنتخلص من تلك المتغيرات المشتركة المزعجة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top