我是靠谱客的博主 迷路板凳,最近开发中收集的这篇文章主要介绍一个打乱列表获得伪随机序列的生成器一个打乱列表获得伪随机序列的生成器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一个打乱列表获得伪随机序列的生成器

  • 偶得一代码,再晚也要记录下来。最近看一本叫游戏编程的书,里面讲到了一种用伪随机的方式实现的洗牌算法。
算法思想是这样的:
算法利用质数和二次方程的数学特性,该算法需要一个质数,他应该大于要遍历的集合元素个数。如果集合中有10个元素,该指数为11,当然这个算法不会生成质数;它只是将一组选定的质数放在一个查询表中。如果需要比较大的质数可以另行生成。其工作原理如下:用3个大于0的随机数计算出一个跳跃值(skip)。这些随机数作为二次方程的系数,而阈值(x)被设置为集合的元素个数;
跳跃值 = 随机数A x (元素个数 x 元素个数)+(随机数B x 元素个数)+随机数C
skip = RandomA * (members * members)+(RandomB * members)+RandomC
有了跳跃值(skip)后,就可以使用下面的代码,以伪随机顺序遍历一次整个集合;
nextMember += skip
nextMember %= prime
skip的值要比集合元素个数大得多,因此选择的值好像是随机跳跃一样

直接上代码吧

//PrimeSearch.h
#pragma once
class PrimeSearch
{
    static int prime_array[];

    int skip;
    int currentPosition;
    int maxElements;
    int *currentPrime;
    int searches;

public:
    PrimeSearch(int elements);
    int GetNext(bool restart = false);
    bool Done() { return (searches == *currentPrime); }
    void Restart() { currentPosition = 0; searches = 0; }
};
//PrimeSearch.cpp
#include "PrimeSearch.h"
#include <stdlib.h>
#include <assert.h>

//#define GCC_ASSERT(a,b) assert(a);
/////////////////////////////////////////////////////////////////////////////
// DEBUG info
/////////////////////////////////////////////////////////////////////////////

#define max(a,b)            (((a) > (b)) ? (a) : (b))

int PrimeSearch::prime_array[] =
{
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
    53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 
    109, 113, 127, 131, 137, 139, 149,  151, 157, 163, 167, 
    173, 179, 181, 191, 193, 197, 199,  211, 223, 227, 229, 
    233, 239, 241,  251, 257, 263, 269, 271, 277, 281, 283, 
    293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 
    367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 
    433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 
    499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 
    577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 
    643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 
    719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 
    797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 
    863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 
    947, 953, 967, 971, 977, 983, 991, 997,

    // after 1000, for space efficiency reasons, 
    // we choose to include fewer prime numbers the bigger the number get.

    1009, 1051, 1103, 1151, 1201, 1259, 1301, 1361, 1409, 1451,
    1511, 1553, 1601, 1657, 1709, 1753, 1801, 1861, 1901, 1951,
    2003, 2053, 2111, 2113, 2153, 2203, 2251,
    2309, 2351, 2411, 2459, 2503, 2551, 2557,
    2609, 2657, 2707, 2753, 2767, 2801, 2851, 2903, 2953,
    3001, 3061, 3109, 3163, 3203, 3251, 3301, 3359, 3407, 3457,
    3511, 3557, 3607, 3659, 3701, 3761, 3803, 3851, 3907, 3967,
    4001, 4051, 4111, 4153, 4201, 4253, 4327, 4357, 4409, 4451,
    4507, 4561, 4603, 4651, 4703, 4751, 4801, 4861, 4903, 4951,

    // begin to skip even more primes

    5003, 5101, 5209, 5303, 5407, 5501, 5623, 5701, 5801, 5903,
    6007, 6101, 6211, 6301, 6421, 6521, 6607, 6701, 6803, 6907,
    7001, 7103, 7207, 7307, 7411, 7507, 7603, 7703, 7817, 7901,
    8009, 8101, 8209, 8311, 8419, 8501, 8609, 8707, 8803, 8923,
    9001, 9103, 9203, 9311, 9403, 9511, 9601, 9719, 9803, 9901,

    // and even more
    10007, 10501, 11003, 11503, 12007, 12503, 13001, 13513, 14009, 14503,
    15013, 15511, 16033, 16519, 17011, 17509, 18013, 18503, 19001, 19501,
    20011, 20507, 21001, 21503, 22003, 22501, 23003, 23509, 24001, 24509

    // if you need more - go get them yourself!!!!
    // Create a bigger array of prime numbers by using this web site: 
    // http://www.rsok.com/~jrm/printprimes.html
};


PrimeSearch::PrimeSearch(int elements)
{
    // "Can't do a PrimeSearch if you have 0 elements to search through, buddy-boy"
    assert(elements>0);

    maxElements = elements;

    int a = (rand() % 13) + 1;
    int b = (rand() % 7) + 1;
    int c = (rand() % 5) + 1;

    skip = (a * maxElements * maxElements) + (b * maxElements) + c;
    skip &= ~0xc0000000;       // 防止跳跃距离过大

    Restart();

    currentPrime = prime_array;
    int s = sizeof(prime_array) / sizeof(prime_array[0]);

    // if this GCC_ASSERT gets hit you didn't have enough prime numbers to deal with this number of 
    // elements. Go back to the web site.
    assert(prime_array[s - 1]>maxElements);

    while (*currentPrime < maxElements)
    {
        currentPrime++;
    }

    int test = skip % *currentPrime;
    if (!test)
        skip++;
}

int PrimeSearch::GetNext(bool restart)
{
    if (restart)
        Restart();

    if (Done())
        return -1;

    bool done = false;

    int nextMember = currentPosition;

    while (!done)
    {
        nextMember = nextMember + skip;
        nextMember %= *currentPrime;
        searches++;

        if (nextMember < maxElements)
        {
            currentPosition = nextMember;
            done = true;
        }
    }
    return currentPosition;
}
//main.cpp
#include <iostream>
#include "PrimeSearch.h"

int main(int argc, char *argv)
{
    int n = 10;
    PrimeSearch pSearch = PrimeSearch(n);
    while (true)
    {
        int getn = pSearch.GetNext();
        if (-1 == getn)
        {
            break;
        }
        std::cout << getn << " ";
    }
    std::cout << std::endl;
    return 0;
}

执行结果如下
执行结果

最后

以上就是迷路板凳为你收集整理的一个打乱列表获得伪随机序列的生成器一个打乱列表获得伪随机序列的生成器的全部内容,希望文章能够帮你解决一个打乱列表获得伪随机序列的生成器一个打乱列表获得伪随机序列的生成器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部