เครื่องมือสร้างตัวเลขสุ่มแบบสุ่มได้


150

Math.random()ฟังก์ชันJavaScript ส่งคืนค่าสุ่มระหว่าง 0 ถึง 1 โดยอัตโนมัติตามเวลาปัจจุบัน (คล้ายกับ Java ฉันเชื่อ) อย่างไรก็ตามฉันไม่คิดว่าจะมีวิธีใดที่จะทำให้คุณเป็นเจ้าของเมล็ดพันธุ์

ฉันจะสร้างตัวสร้างตัวเลขสุ่มที่ฉันสามารถให้ค่าเมล็ดของตัวเองได้อย่างไรเพื่อที่ฉันจะสามารถสร้างลำดับสุ่ม (หลอก) ตัวเลขซ้ำได้?


1
หมายเหตุ: เพื่อประโยชน์ในการทำให้คำถามนี้สั้นและมุ่งเน้นฉันได้แบ่งรหัสที่เป็นปัญหาด้านบนออกเป็นคำตอบของ Community Wikiด้านล่าง
Ilmari Karonen

คำตอบ:


124

ทางเลือกหนึ่งคือhttp://davidbau.com/seedrandomซึ่งเป็นดรอปดาวน์แบบแทนที่ Math.random () แบบ RC4 ซึ่งใช้เมล็ดได้


18
seedrandom เดวิด Bau ได้กลายเป็นที่นิยมพอที่เขายืนยันว่านี่บน GitHub มันเป็นความอัปยศที่ ECMAScript เป็นฉากหลังมานานแล้วว่าสิ่งนี้ไม่รวมอยู่ในภาษา อย่างจริงจังไม่มีการเพาะ !!!
กินที่ Joes

2
@EatJoe มันเป็นทั้งความอัปยศและศักดิ์ศรีของ JS ว่านี่เป็นทั้งที่จำเป็นและเป็นไปได้ มันค่อนข้างเจ๋งที่คุณสามารถรวมไฟล์เดียวและรับการเปลี่ยนแปลงที่เข้ากันได้กับวัตถุทางคณิตศาสตร์ ไม่เลวสำหรับงาน 10 วันเบรนแดนเอช
Bruno Bronosky

2
สำหรับใครที่กำลังมองหาหน้า npm สำหรับโครงการนี้: npmjs.com/package/seedrandom
Kip

27

หากคุณไม่ต้องการความสามารถในการเพาะให้ใช้Math.random()และสร้างฟังก์ชันตัวช่วยรอบตัวมัน (เช่นrandRange(start, end))

ฉันไม่แน่ใจว่าคุณใช้ RNG อย่างไร แต่เป็นการดีที่สุดที่จะทราบและจัดทำเอกสารเพื่อให้คุณทราบถึงลักษณะและข้อ จำกัด ของมัน

เช่นเดียวกับ Starkii กล่าวว่า Mersenne Twister เป็น PRNG ที่ดี แต่มันไม่ง่ายที่จะนำไปใช้ หากคุณต้องการทำด้วยตัวเองลองใช้ LCG - มันง่ายมากมีคุณสมบัติการสุ่มที่เหมาะสม (ไม่ดีเท่า Mersenne Twister) และคุณสามารถใช้ค่าคงที่ยอดนิยมบางส่วนได้

แก้ไข: พิจารณาตัวเลือกที่ยอดเยี่ยมที่คำตอบนี้สำหรับการใช้งาน RNG แบบสั้นได้รวมถึงตัวเลือก LCG

function RNG(seed) {
  // LCG using GCC's constants
  this.m = 0x80000000; // 2**31;
  this.a = 1103515245;
  this.c = 12345;

  this.state = seed ? seed : Math.floor(Math.random() * (this.m - 1));
}
RNG.prototype.nextInt = function() {
  this.state = (this.a * this.state + this.c) % this.m;
  return this.state;
}
RNG.prototype.nextFloat = function() {
  // returns in range [0,1]
  return this.nextInt() / (this.m - 1);
}
RNG.prototype.nextRange = function(start, end) {
  // returns in range [start, end): including start, excluding end
  // can't modulu nextInt because of weak randomness in lower bits
  var rangeSize = end - start;
  var randomUnder1 = this.nextInt() / this.m;
  return start + Math.floor(randomUnder1 * rangeSize);
}
RNG.prototype.choice = function(array) {
  return array[this.nextRange(0, array.length)];
}

var rng = new RNG(20);
for (var i = 0; i < 10; i++)
  console.log(rng.nextRange(10, 50));

var digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
for (var i = 0; i < 10; i++)
  console.log(rng.choice(digits));


2
โมดูลัสไม่ควรเป็น 2 ^ 31? ผมอ่านขั้นตอนวิธีการนี้จากวิกิพีเดีย
Trantor Liu

3
เพื่อให้คุณทราบว่านี่ไม่ใช่ "ถูกต้อง" ในแง่ที่ว่ามันไม่ได้ส่งออกสิ่งที่คณิตศาสตร์สั่งการ กล่าวอีกนัยหนึ่งภาษาที่สามารถจัดการกับจำนวนมากเหล่านั้นจะมีผลลัพธ์ที่แตกต่างกัน JS ทำให้เกิดความแม่นยำในจำนวนมากและสับ (พวกเขาลอยหลังจากทั้งหมด)
ท.บ.

4
-1 การใช้ LCG นี้ไม่ จำกัด จำนวนเต็มที่แน่นอนใน JavaScript เนื่องจากthis.a * this.stateมีแนวโน้มที่จะส่งผลให้มีจำนวนมากกว่า 2 ^ 53 ผลที่ได้คือช่วงเอาท์พุทที่ จำกัด และสำหรับบางเมล็ดอาจเป็นช่วงเวลาสั้น ๆ โดยทั่วไปแล้วการใช้กำลังสองเพื่อmให้ได้รูปแบบที่ชัดเจนมากเมื่อคุณใช้โมดูลัสการดำเนินการมากกว่าการตัดทอนอย่างง่ายอย่างไรก็ตามก็ไม่มีเหตุผลที่จะไม่ใช้นายก
aaaaaaaaaaaa

22

หากคุณต้องการระบุเมล็ดคุณต้องเปลี่ยนการเรียกไปที่getSeconds()และgetMinutes()และคุณสามารถผ่านใน int และใช้ครึ่งหนึ่งของมัน mod 60 สำหรับค่าวินาทีและอีกครึ่งโมดูโล 60 เพื่อให้ส่วนอื่น ๆ

ที่ถูกกล่าวว่าวิธีนี้ดูเหมือนขยะ การสร้างหมายเลขสุ่มที่เหมาะสมนั้นทำได้ยากมาก ปัญหาที่ชัดเจนเกี่ยวกับสิ่งนี้คือการที่การสุ่มหมายเลขขึ้นอยู่กับวินาทีและนาที ในการคาดเดาเมล็ดพันธุ์และสร้างสตรีมของตัวเลขสุ่มของคุณต้องลองชุดที่สองและนาทีที่แตกต่างกัน 3600 นอกจากนี้ยังหมายความว่ามีเมล็ดที่เป็นไปได้ที่แตกต่างกันเพียง 3600 สิ่งนี้สามารถแก้ไขได้ แต่ฉันสงสัย RNG นี้ตั้งแต่เริ่มต้น

หากคุณต้องการใช้ RNG ที่ดีขึ้นลองใช้Mersenne TwisterTwister มันเป็น RNG ที่ผ่านการทดสอบอย่างดีและแข็งแกร่งพอสมควรพร้อมวงโคจรขนาดใหญ่และประสิทธิภาพที่ยอดเยี่ยม

แก้ไข: ฉันควรจะถูกต้องจริงและอ้างถึงนี้เป็นเครื่องกำเนิดตัวเลขสุ่มหลอกหรือ PRNG

"ทุกคนที่ใช้วิธีการทางคณิตศาสตร์ในการสร้างตัวเลขสุ่มอยู่ในสถานะของบาป"
                                                                                                                                                          --- จอห์นฟอนนอยมันน์


1
ลิงก์ไปยังการใช้งาน JS ของ Mersenne Twister: math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/JAVASCRIPT/ …
orip

1
@orip คุณมีแหล่งข้อมูลสำหรับสถานะเริ่มต้น 3600 หรือไม่? Mersenne Twister เกิดจากจำนวน 32 บิตดังนั้น PRNG ควรมีสถานะเริ่มต้น 4 พันล้านสถานะ - เฉพาะในกรณีที่เมล็ดเริ่มต้นนั้นสุ่มอย่างแท้จริง
Tobias P.

2
@TobiasP ฉันอ้างถึงข้อเสนอแนะในการเพาะปลูกด้วยการรวมกันของ getSeconds () และ getMinutes (), 60 * 60 == 3600 สถานะเริ่มต้นที่เป็นไปได้ ฉันไม่ได้อ้างถึง Mersenne Twister
orip

3
@orip Ok ไม่ชัดเจน คุณได้รับเกี่ยวกับ Mersenne Twister และในประโยคถัดไปเกี่ยวกับรัฐ inital;)
Tobias P.

2
ผู้ถามคำถามไม่ได้กล่าวถึงใด ๆ ว่าพวกเขาต้องการการสร้างหมายเลขแบบสุ่ม "เหมาะสม" สำหรับแอปพลิเคชันที่มีความละเอียดอ่อนแบบเข้ารหัส ในขณะที่คำตอบทั้งหมดเป็นจริงเฉพาะย่อหน้าแรกเท่านั้นที่เกี่ยวข้องกับคำถามที่ถาม อาจเพิ่มข้อมูลโค้ดของโซลูชันที่แนะนำ
V. Rubinetti

12

ฉันใช้พอร์ต JavaScript ของ Mersenne Twister: https://gist.github.com/300494 จะช่วยให้คุณตั้งค่าเมล็ดด้วยตนเอง นอกจากนี้ตามที่กล่าวไว้ในคำตอบอื่น ๆ Mersenne Twister เป็น PRNG ที่ดีจริงๆ


8

รหัสที่คุณระบุชนิดของรูปลักษณ์เหมือนLehmer RNG หากเป็นเช่นนี้แสดงว่า2147483647เป็นจำนวนเต็ม214748364732 บิตที่ใหญ่ที่สุดและเป็น 32- บิตที่ใหญ่ที่สุดและ48271เป็นตัวคูณเต็มช่วงเวลาที่ใช้ในการสร้างตัวเลข

หากเป็นจริงคุณสามารถแก้ไขRandomNumberGeneratorเพื่อรับพารามิเตอร์พิเศษseedจากนั้นตั้งthis.seedเป็นseed; แต่คุณต้องระวังให้ดีเพื่อให้แน่ใจว่าเมล็ดจะส่งผลให้มีการแจกแจงตัวเลขที่ดี (Lehmer สามารถเป็นแบบนี้) - แต่เมล็ดส่วนใหญ่จะใช้ได้


7

ต่อไปนี้เป็น PRNG ที่อาจได้รับเมล็ดที่กำหนดเอง การโทรSeedRandomจะส่งคืนฟังก์ชันตัวสร้างแบบสุ่มSeedRandomสามารถถูกเรียกได้โดยไม่มีข้อโต้แย้งเพื่อให้ฟังก์ชันการสุ่มส่งคืนด้วยเวลาปัจจุบันหรือสามารถถูกเรียกด้วย 1 หรือ 2 ที่ไม่เป็นลบระหว่างการขัดแย้งเพื่อให้ได้ผลลัพธ์เป็นจำนวนเต็มเหล่านั้น เนื่องจากการหว่านความแม่นยำของจุดลอยที่มีเพียง 1 ค่าจะทำให้เครื่องกำเนิดไฟฟ้าสามารถเริ่มสถานะใดสถานะหนึ่งใน 2 ^ 53

ฟังก์ชั่นเครื่องกำเนิดไฟฟ้าแบบสุ่มที่ส่งกลับมาใช้เวลา 1 อาร์กิวเมนต์จำนวนเต็มชื่อตั้งชื่อlimitขีด จำกัด จะต้องอยู่ในช่วง 1 ถึง 4294965886 ฟังก์ชั่นจะกลับจำนวนในช่วง 0 ถึงขีด จำกัด -1

function SeedRandom(state1,state2){
    var mod1=4294967087
    var mul1=65539
    var mod2=4294965887
    var mul2=65537
    if(typeof state1!="number"){
        state1=+new Date()
    }
    if(typeof state2!="number"){
        state2=state1
    }
    state1=state1%(mod1-1)+1
    state2=state2%(mod2-1)+1
    function random(limit){
        state1=(state1*mul1)%mod1
        state2=(state2*mul2)%mod2
        if(state1<limit && state2<limit && state1<mod1%limit && state2<mod2%limit){
            return random(limit)
        }
        return (state1+state2)%limit
    }
    return random
}

ตัวอย่างการใช้:

var generator1=SeedRandom() //Seed with current time
var randomVariable=generator1(7) //Generate one of the numbers [0,1,2,3,4,5,6]
var generator2=SeedRandom(42) //Seed with a specific seed
var fixedVariable=generator2(7) //First value of this generator will always be
                                //1 because of the specific seed.

ตัวสร้างนี้แสดงคุณสมบัติต่อไปนี้:

  • มันมีสถานะภายในเป็นไปได้ต่างกันประมาณ 2 ^ 64
  • มันมีช่วงเวลาประมาณ 2 ^ 63 มีอะไรมากกว่าที่ใคร ๆ จะต้องใช้ในโปรแกรม JavaScript
  • เนื่องจากmodค่าที่เป็นช่วงเวลาไม่มีรูปแบบง่าย ๆ ในเอาต์พุตไม่ว่าจะมีขีด จำกัด ที่เลือกหรือไม่ ซึ่งแตกต่างจาก PRNG ที่ง่ายกว่าซึ่งแสดงรูปแบบที่ค่อนข้างเป็นระบบ
  • มันทิ้งผลลัพธ์บางอย่างเพื่อให้ได้การกระจายที่สมบูรณ์แบบไม่ว่าจะมีขีด จำกัด
  • มันค่อนข้างช้าวิ่งประมาณ 10,000,000 ครั้งต่อวินาทีบนเครื่องของฉัน

2
ทำไมสิ่งนี้ถึงสร้างรูปแบบ? for (var i = 0; i < 400; i++) { console.log("input: (" + i * 245 + ", " + i * 553 + ") | output: " + SeedRandom(i * 245, i * 553)(20)); }
Timothy Kanski

@TimothyKanski เพราะคุณใช้ผิด ฉันไม่มีความเชี่ยวชาญ แต่สิ่งนี้เกิดขึ้นเพราะคุณกำลังเริ่มต้นตัวสร้างในแต่ละการวนซ้ำเพียงเห็นค่าแรกของมันตามเมล็ดและไม่วนซ้ำตามจำนวนตัวกำเนิด ฉันเชื่อว่าสิ่งนี้จะเกิดขึ้นใน PRNG ใด ๆ ที่ไม่ได้แฮชเมล็ดในช่วงเวลาที่ระบุ
bryc

5

หากคุณโปรแกรมใน typescript ฉันปรับการใช้งาน Mersenne Twister ที่นำมาในคำตอบของ Christoph Henkelmann กับหัวข้อนี้เป็นคลาส typescript:

/**
 * copied almost directly from Mersenne Twister implementation found in https://gist.github.com/banksean/300494
 * all rights reserved to him.
 */
export class Random {
    static N = 624;
    static M = 397;
    static MATRIX_A = 0x9908b0df;
    /* constant vector a */
    static UPPER_MASK = 0x80000000;
    /* most significant w-r bits */
    static LOWER_MASK = 0x7fffffff;
    /* least significant r bits */

    mt = new Array(Random.N);
    /* the array for the state vector */
    mti = Random.N + 1;
    /* mti==N+1 means mt[N] is not initialized */

    constructor(seed:number = null) {
        if (seed == null) {
            seed = new Date().getTime();
        }

        this.init_genrand(seed);
    }

    private init_genrand(s:number) {
        this.mt[0] = s >>> 0;
        for (this.mti = 1; this.mti < Random.N; this.mti++) {
            var s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30);
            this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253)
                + this.mti;
            /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
            /* In the previous versions, MSBs of the seed affect   */
            /* only MSBs of the array mt[].                        */
            /* 2002/01/09 modified by Makoto Matsumoto             */
            this.mt[this.mti] >>>= 0;
            /* for >32 bit machines */
        }
    }

    /**
     * generates a random number on [0,0xffffffff]-interval
     * @private
     */
    private _nextInt32():number {
        var y:number;
        var mag01 = new Array(0x0, Random.MATRIX_A);
        /* mag01[x] = x * MATRIX_A  for x=0,1 */

        if (this.mti >= Random.N) { /* generate N words at one time */
            var kk:number;

            if (this.mti == Random.N + 1)   /* if init_genrand() has not been called, */
                this.init_genrand(5489);
            /* a default initial seed is used */

            for (kk = 0; kk < Random.N - Random.M; kk++) {
                y = (this.mt[kk] & Random.UPPER_MASK) | (this.mt[kk + 1] & Random.LOWER_MASK);
                this.mt[kk] = this.mt[kk + Random.M] ^ (y >>> 1) ^ mag01[y & 0x1];
            }
            for (; kk < Random.N - 1; kk++) {
                y = (this.mt[kk] & Random.UPPER_MASK) | (this.mt[kk + 1] & Random.LOWER_MASK);
                this.mt[kk] = this.mt[kk + (Random.M - Random.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
            }
            y = (this.mt[Random.N - 1] & Random.UPPER_MASK) | (this.mt[0] & Random.LOWER_MASK);
            this.mt[Random.N - 1] = this.mt[Random.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];

            this.mti = 0;
        }

        y = this.mt[this.mti++];

        /* Tempering */
        y ^= (y >>> 11);
        y ^= (y << 7) & 0x9d2c5680;
        y ^= (y << 15) & 0xefc60000;
        y ^= (y >>> 18);

        return y >>> 0;
    }

    /**
     * generates an int32 pseudo random number
     * @param range: an optional [from, to] range, if not specified the result will be in range [0,0xffffffff]
     * @return {number}
     */
    nextInt32(range:[number, number] = null):number {
        var result = this._nextInt32();
        if (range == null) {
            return result;
        }

        return (result % (range[1] - range[0])) + range[0];
    }

    /**
     * generates a random number on [0,0x7fffffff]-interval
     */
    nextInt31():number {
        return (this._nextInt32() >>> 1);
    }

    /**
     * generates a random number on [0,1]-real-interval
     */
    nextNumber():number {
        return this._nextInt32() * (1.0 / 4294967295.0);
    }

    /**
     * generates a random number on [0,1) with 53-bit resolution
     */
    nextNumber53():number {
        var a = this._nextInt32() >>> 5, b = this._nextInt32() >>> 6;
        return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
    }
}

คุณสามารถใช้มันได้มากกว่านี้:

var random = new Random(132);
random.nextInt32(); //return a pseudo random int32 number
random.nextInt32([10,20]); //return a pseudo random int in range [10,20]
random.nextNumber(); //return a a pseudo random number in range [0,1]

ตรวจสอบแหล่งที่มาสำหรับวิธีการเพิ่มเติม


0

หมายเหตุ:รหัสนี้เดิมรวมอยู่ในคำถามข้างต้น เพื่อให้คำถามสั้นและมุ่งเน้นฉันได้ย้ายไปยังคำตอบของ Wiki ชุมชนนี้

ฉันพบรหัสนี้และดูเหมือนว่าจะทำงานได้ดีสำหรับการรับหมายเลขสุ่มแล้วใช้เมล็ดหลังจากนั้น แต่ฉันไม่แน่ใจว่าตรรกะทำงานอย่างไร (เช่นที่หมายเลข 2345678901, 48271 & 2147483647 มาจาก)

function nextRandomNumber(){
  var hi = this.seed / this.Q;
  var lo = this.seed % this.Q;
  var test = this.A * lo - this.R * hi;
  if(test > 0){
    this.seed = test;
  } else {
    this.seed = test + this.M;
  }
  return (this.seed * this.oneOverM);
}

function RandomNumberGenerator(){
  var d = new Date();
  this.seed = 2345678901 + (d.getSeconds() * 0xFFFFFF) + (d.getMinutes() * 0xFFFF);
  this.A = 48271;
  this.M = 2147483647;
  this.Q = this.M / this.A;
  this.R = this.M % this.A;
  this.oneOverM = 1.0 / this.M;
  this.next = nextRandomNumber;
  return this;
}

function createRandomNumber(Min, Max){
  var rand = new RandomNumberGenerator();
  return Math.round((Max-Min) * rand.next() + Min);
}

//Thus I can now do:
var letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var numbers = ['1','2','3','4','5','6','7','8','9','10'];
var colors = ['red','orange','yellow','green','blue','indigo','violet'];
var first = letters[createRandomNumber(0, letters.length)];
var second = numbers[createRandomNumber(0, numbers.length)];
var third = colors[createRandomNumber(0, colors.length)];

alert("Today's show was brought to you by the letter: " + first + ", the number " + second + ", and the color " + third + "!");

/*
  If I could pass my own seed into the createRandomNumber(min, max, seed);
  function then I could reproduce a random output later if desired.
*/

3
ว้าว, ฟังก์ชั่นRandomNumberGeneratorและnextRandomNumberวันที่จริงตลอดทางกลับไปปี 1996 มันควรจะเป็น Lehmer / LCG RNG มันใช้คณิตศาสตร์ที่ฉลาดบางอย่างเพื่อดำเนินการคำนวณแบบโมดูโลในจำนวนเต็ม 32 บิตที่มิฉะนั้นจะเล็กเกินไปที่จะมีค่ากลางบางอย่าง สิ่งที่เป็นคือ JavaScript ไม่ได้ใช้จำนวนเต็ม 32 บิต แต่เป็น 64 บิตลอยตัวและเนื่องจากการแบ่งไม่ได้เป็นจำนวนเต็มเช่นรหัสนี้ทึกทักผลที่ได้ไม่ใช่ตัวกำเนิด Lehmer มันให้ผลลัพธ์ที่ดูเหมือนสุ่ม แต่การรับประกันของเครื่องกำเนิด Lehmer ไม่ได้ใช้
aaaaaaaaaaaa

1
createRandomNumberฟังก์ชั่นหลังจากนั้นก็ไม่ผิดทุกอย่างสวยมากสะดุดตาที่สุดมัน instantiates RNG ใหม่ทุกครั้งที่มันถูกเรียกว่าซึ่งหมายความว่าการโทรในเวลาอันรวดเร็วทั้งหมดจะใช้ลอยเดียวกัน ในรหัสให้มันเป็นไปไม่ได้เกือบ'a'ที่จะจับคู่กับอะไร แต่และ'1' 'red'
aaaaaaaaaaaa

-2

ตกลงนี่คือวิธีแก้ปัญหาที่ฉันตัดสิน

ขั้นแรกคุณต้องสร้างค่าเมล็ดโดยใช้ฟังก์ชัน "newseed ()" จากนั้นคุณส่งค่าเมล็ดไปยังฟังก์ชัน "srandom ()" สุดท้ายฟังก์ชัน "srandom ()" จะส่งคืนค่าหลอกเทียมระหว่าง 0 ถึง 1

บิตสำคัญคือค่าเมล็ดถูกเก็บไว้ในอาร์เรย์ หากเป็นเพียงจำนวนเต็มหรือจำนวนลอยค่าจะได้รับการเขียนทับทุกครั้งที่มีการเรียกใช้ฟังก์ชันเนื่องจากค่าของจำนวนเต็มจำนวนลอยสตริงและอื่น ๆ จะถูกเก็บไว้โดยตรงในสแต็กแทนที่จะเป็นพอยน์เตอร์ในกรณีของอาร์เรย์และ วัตถุอื่น ๆ ดังนั้นจึงเป็นไปได้ที่คุณค่าของเมล็ดจะยังคงอยู่

ในที่สุดก็เป็นไปได้ที่จะกำหนดฟังก์ชั่น "srandom ()" ว่ามันเป็นวิธีการของวัตถุ "คณิตศาสตร์" แต่ฉันจะปล่อยให้มันขึ้นอยู่กับคุณที่จะคิดออก ;)

โชคดี!

JavaScript:

// Global variables used for the seeded random functions, below.
var seedobja = 1103515245
var seedobjc = 12345
var seedobjm = 4294967295 //0x100000000

// Creates a new seed for seeded functions such as srandom().
function newseed(seednum)
{
    return [seednum]
}

// Works like Math.random(), except you provide your own seed as the first argument.
function srandom(seedobj)
{
    seedobj[0] = (seedobj[0] * seedobja + seedobjc) % seedobjm
    return seedobj[0] / (seedobjm - 1)
}

// Store some test values in variables.
var my_seed_value = newseed(230951)
var my_random_value_1 = srandom(my_seed_value)
var my_random_value_2 = srandom(my_seed_value)
var my_random_value_3 = srandom(my_seed_value)

// Print the values to console. Replace "WScript.Echo()" with "alert()" if inside a Web browser.
WScript.Echo(my_random_value_1)
WScript.Echo(my_random_value_2)
WScript.Echo(my_random_value_3)

Lua 4 (สภาพแวดล้อมเป้าหมายส่วนตัวของฉัน):

-- Global variables used for the seeded random functions, below.
seedobja = 1103515.245
seedobjc = 12345
seedobjm = 4294967.295 --0x100000000

-- Creates a new seed for seeded functions such as srandom().
function newseed(seednum)
    return {seednum}
end

-- Works like random(), except you provide your own seed as the first argument.
function srandom(seedobj)
    seedobj[1] = mod(seedobj[1] * seedobja + seedobjc, seedobjm)
    return seedobj[1] / (seedobjm - 1)
end

-- Store some test values in variables.
my_seed_value = newseed(230951)
my_random_value_1 = srandom(my_seed_value)
my_random_value_2 = srandom(my_seed_value)
my_random_value_3 = srandom(my_seed_value)

-- Print the values to console.
print(my_random_value_1)
print(my_random_value_2)
print(my_random_value_3)

ป.ล. - ฉันยังไม่คุ้นเคยกับ Stack Overflow แต่ทำไมไม่โพสต์ตามลำดับเวลา
posfan12

สวัสดี @ posfan12 - คำตอบสำหรับคำถามที่มักจะมีการระบุไว้ในคำสั่งของ "upvotes" เช่น "ครีมขึ้นไปด้านบน" อย่างไรก็ตามเพื่อให้แน่ใจว่าการดูคำตอบอย่างยุติธรรมด้วยคะแนนเดียวกันพวกเขาจะแสดงตามลำดับแบบสุ่ม ตั้งแต่นี้เป็นคำถามของฉันเดิม ;-) ฉันจะต้องแน่ใจว่าได้ตรวจสอบในไม่ช้า หากฉัน (หรือคนอื่น ๆ ) พบคำตอบนี้มีประโยชน์เราจะถอนคำตอบและถ้าฉันคิดว่ามันเป็นคำตอบที่ "ถูกต้อง" คุณจะเห็นเครื่องหมายถูกสีเขียวที่เพิ่มเข้าไปในคำตอบนี้เช่นกัน - ยินดีต้อนรับสู่ StackOverflow!
scunliffe

2
-1 การใช้งาน LCG นี้ทำให้ขีด จำกัด ของจำนวนเต็มที่แน่นอนใน JavaScript เนื่องจากseedobj[0] * seedobjaมีแนวโน้มที่จะส่งผลให้มีจำนวนมากกว่า 2 ^ 53 ผลที่ได้คือช่วงเอาท์พุทที่ จำกัด และสำหรับบางเมล็ดอาจเป็นช่วงเวลาสั้น ๆ
aaaaaaaaaaaa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.