热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

快速生成随机出现的随机数-Fastgenerationofrandomnumbersthatappearrandom

Iamlookingforanefficientwaytogeneratenumbersthatahumanwouldperceiveasbeingrandom.B

I am looking for an efficient way to generate numbers that a human would perceive as being random. Basically, I think of this as avoiding long sequences of 0 or 1 bits. I expect humans to be viewing the bit pattern, and a very low powered cpu should be able to calculate near a thousand of these per second.

我正在寻找一种有效的方法来生成人类认为是随机的数字。基本上,我认为这避免了0或1位的长序列。我希望人类能够查看位模式,而非常低功耗的CPU应该能够计算出每秒近千个这样的数据。

There are two different concepts that I can think of to do this, but I am lost finding a efficient way of accomplishing them.

我可以想到有两个不同的概念来做这件事,但我找不到找到一种有效的方法来完成它们。

  1. Generate a random number with a fixed number of one bits. For a 32-bit random number, this requires up to 31 random numbers, using the Knuth selection algorithm. is there a more efficient way to generate a random number with some number of bits set? Unfortunately, 0000FFFF doesn't look very random.

    生成具有固定数量的一位的随机数。对于32位随机数,使用Knuth选择算法需要多达31个随机数。是否有更有效的方法来生成一个具有一定数量的位的随机数?不幸的是,0000FFFF看起来不是很随机。

  2. Some form of "part-wise' density seems like it'd look better - but I can't come up with a clear way of doing so - I'd imagine going through each chunk, and calculate how far it is from the ideal density, and try to increase the bit density of the next chunk. This sounds complex.

    某种形式的“部分”密度似乎看起来更好 - 但我无法想出这样做的明确方法 - 我想象一下每个块,并计算它与理想的距离密度,并尝试增加下一个块的位密度。这听起来很复杂。

Hopefully there's another algorithm that I haven't thought about for this. Thanks in advance for your help.

希望还有另一种算法,我没想过这个。在此先感谢您的帮助。

[EDIT] I should be clearer with what I ask -
(a) Is there an efficient way to generate random numbers without "long" runs of a single bit, where "long" is a tunable parameter?
(b) Other suggestions on what would make a number appear to be less-random?

[编辑]我应该更清楚我的要求 - (a)有没有一种有效的方法来生成随机数而不需要“长”运行一个位,其中“long”是一个可调参数? (b)关于什么会使一个数字看起来不那么随意的其他建议?

12 个解决方案

#1


A linear feedback shift register probably does what you want.

线性反馈移位寄存器可能会做你想要的。

Edit in light of an updated question: You should look at a shuffle bag, although I'm not sure how fast this could run. See also this question.

根据更新的问题进行编辑:你应该看一个洗牌包,虽然我不确定它能跑得多快。另见这个问题。

#2


I don't really know what you mean by bit patterns that "look" random. Is there some algorithm for defining what that is? One way might be to formulate an array consisting of only those numbers which are random enough for your purpose, then, randomly select elements from that array and push them onto the stream. The thing you seem to be trying to do seems bizarre to me and may be doomed to failure though. What happens if you have two 32 bit numbers which taken individually would meet your criteria for apparent randomicity, but when placed side by side make a sufficiently long stream of 0's or 1's to look made up?

我真的不知道“看起来”随机的位模式是什么意思。是否有一些算法来定义它是什么?一种方法可能是制定一个数组,该数组只包含那些随机足以满足您的目的的数字,然后从该数组中随机选择元素并将它们推送到流中。你似乎想要做的事情对我来说似乎很奇怪,但可能注定要失败。如果您有两个单独的32位数字符合您的表观随机性标准会发生什么,但是当并排放置时,会产生一个足够长的0或1的流来组成?

Finally, I couldn't resist this.

最后,我无法抗拒这一点。


#3


You need to decide by exactly what rules you decide if something "looks random". Then you take a random number generator that produces enough "real randomness" for your purpose, and every time it generates a number that doesn't look random enough, you throw that number away and generate a new one.

如果“看起来像是随机的”,你需要确定你决定的规则。然后你拿一个随机数生成器,为你的目的产生足够的“真实随机性”,每当它生成一个看起来不够随机的数字时,你抛出那个数字并生成一个新的数字。

Or you directly produce a sequence of "random" bits and every time the random generator outputs the "wrong" next bit (that would make it look not-random), you just flip that bit.

或者你直接产生一系列“随机”位,每次随机发生器输出“错误”的下一位(这会使它看起来不是随机的),你只需翻转那一位。

#4


Here's what I'd do. I'd use a number like 00101011100101100110100101100101 and rotate it by some random amount each time.

这就是我要做的。我会使用像00101011100101100110100101100101这样的数字并每次随机旋转它。

But are you sure that a typical pseudo random generator wouldn't do? Have you tried it? You con't very many long strings of 0s and 1s anyhow.

但你确定一个典型的伪随机发生器不会这样做吗?你试过吗?无论如何,你不会有很多长串的0和1。

If you're going to use a library random number and you're worried about too many or too few bits being set, there are cheap ways of counting bits.

如果您要使用库随机数并且您担心设置的位太多或太少,则可以通过便宜的方式对位进行计数。

#5


Random numbers often have long sequences of 1s and 0s, so I'm not sure I fully understand why you can't use a simple linear congruential generator and shift in or out how ever many bits you need. They're blazing fast, look extremely random to the naked eye, and you can choose coefficients that will yield random integers in whatever positive range you need. If you need 32 "random looking" bits, just generate four random numbers and take the low 8 bits from each.

随机数通常有1和0的长序列,所以我不确定我完全理解为什么你不能使用简单的线性同余生成器并移入或移出你需要的多少位。它们非常快速,肉眼看起来非常随机,你可以选择在你需要的任何正范围内产生随机整数的系数。如果你需要32个“随机查找”位,只需生成四个随机数并从每个位取低8位。

You don't really need to implement your own at all though, since in most languages the random library already implements one.

你根本不需要实现自己的,因为在大多数语言中,随机库已经实现了一个。

If you're determined that you want a particular density of 1s, though, you could always start with a number that has the required number of 1s set

但是,如果您确定要特定密度为1,则始终可以从具有所需数量1的数字开始

int a = 0x00FF;

then use a bit twiddling hack to implement a bit-level shuffle of the bits in that number.

然后使用一些麻烦的黑客实现该数字位的位级混乱。

#6


If you are looking to avoid long runs, how about something simple like:

如果你想避免长跑,那么简单的事情如下:

#include 

class generator {
public:
   generator() : last_num(0), run_count(1) { }

   bool next_bit() {
      const bool flip = rand() > RAND_MAX / pow( 2, run_count);
                               // RAND_MAX >> run_count ? 
      if(flip) {
         run_count = 1;
         last_num = !last_num;
      } else
         ++run_count;

      return last_num;
   }
private:
   bool last_num;
   int run_count;
};

Runs become less likely the longer they go on. You could also do RAND_MAX / 1+run_count if you wanted longer runs

运行的时间越长,运行的可能性就越小。如果你想要更长的跑步,你也可以做RAND_MAX / 1 + run_count

#7


Since you care most about run length, you could generate random run lengths instead of random bits, so as to give them the exact distribution you want.

由于您最关心的是运行长度,因此您可以生成随机运行长度而不是随机位,以便为它们提供所需的精确分布。

The mean run length in random binary data is of course 4 (sum of n/(2^(n-1))), and the mode average 1. Here are some random bits (I swear this is a single run, I didn't pick a value to make my point):

随机二进制数据的平均运行长度当然是4(n /(2 ^(n-1))之和)和模式平均值1.这里有一些随机位(我发誓这是一次运行,我没有选择一个值来表明我的观点):

0111111011111110110001000101111001100000000111001010101101001000

See there's a run length of 8 in there. This is not especially surprising, since run length 8 should occur roughly every 256 bits and I've generated 64 bits.

看那里的跑步长度为8。这并不特别令人惊讶,因为运行长度8应该大约每256位发生一次,并且我生成了64位。

If this doesn't "look random" to you because of excessive run lengths, then generate run lengths with whatever distribution you want. In pseudocode:

如果由于运行长度过长而不“随机”,则生成所需分布的运行长度。在伪代码中:

loop
    get a random number
    output that many 1 bits
    get a random number
    output that many 0 bits
endloop

You'd probably want to discard some initial data from the stream, or randomise the first bit, to avoid the problem that as it stands, the first bit is always 1. The probability of the Nth bit being 1 depends on how you "get a random number", but for anything that achieves "shortish but not too short" run lengths it will soon be as close to 50% as makes no difference.

您可能想要从流中丢弃一些初始数据,或者将第一位随机化,以避免出现问题,第一位始终为1.第N位为1的概率取决于您“获得”的方式一个随机数字“,但对于任何达到”短暂但不太短“的运行长度,它将很快接近50%,因为没有区别。

For instance "get a random number" might do this:

例如,“获取随机数”可能会这样做:

get a uniformly-distributed random number n from 1 to 81
if n is between 1 and 54, return 1
if n is between 55 and 72, return 2
if n is between 72 and 78, return 3
if n is between 79 and 80, return 4
return 5

The idea is that the probability of a run of length N is one third the probability of a run of length N-1, instead of one half. This will give much shorter average run lengths, and a longest run of 5, and would therefore "look more random" to you. Of course it would not "look random" to anyone used to dealing with sequences of coin tosses, because they'd think the runs were too short. You'd also be able to tell very easily with statistical tests that the value of digit N is correlated with the value of digit N-1.

这个想法是长度N的运行概率是长度N-1运行概率的三分之一,而不是一半。这将使平均运行时间缩短得多,并且最长运行时间为5,因此对您来说“看起来更随机”。当然,任何习惯于处理硬币投掷序列的人都不会“看起来随意”,因为他们认为跑步太短了。您还可以通过统计测试很容易地判断出数字N的值与数字N-1的值相关。

This code uses at least log(81) = 6.34 "random bits" to generate on average 1.44 bits of output, so is slower than just generating uniformly-distributed bits. But it shouldn't be much more than about 7/1.44 = 5 times slower, and a LFSR is pretty fast to start with.

此代码至少使用log(81)= 6.34“随机位”来生成平均1.44位的输出,因此比生成均匀分布的位慢。但它应该不会超过7 / 1.44 = 5倍慢,而LFSR开始时速度相当快。

#8


This is how I would examine the number:

这是我如何检查数字:

const int max_repeated_bits = 4;  /* or any other number that you prefer */

int examine_1(unsigned int x) {      
  for (int i=0; i

Then, just generate a number x, if examine(x) return 0, reject it and try again. The probability to get a 32-bit number with more than 4 bits in a row is about 2/3, so you would need about 3 random generator callse per number. However, If you allow more than 4 bits, it gets better. Say, the probability to get more than 6 bits in a row only about 20%, so you would need only 1.25 calls per number.

然后,只需生成一个数字x,如果检查(x)返回0,拒绝它并再试一次。连续获得一个超过4位的32位数的概率约为2/3,因此每个数字需要大约3个随机生成器callse。但是,如果允许超过4位,则会变得更好。比如说,连续获得超过6位的概率只有20%左右,因此每个数字只需要1.25个呼叫。

#9


There are various variants of linear feedback shift registers, such as shrinking and self-shrinking which modify the output of one LFSR based on the output of another.

线性反馈移位寄存器有各种变体,例如收缩和自收缩,它们根据另一个LFSR的输出修改一个LFSR的输出。

The design of these attempts to create random numbers, where the probability of getting two bits the same in a row is 0.5, of getting three in a row is 0.25 as so on.

这些尝试创建随机数的设计,其中连续两位获得两位的概率为0.5,连续三次获得的概率为0.25,因此依此类推。

It should be possible to chain two LFSRs to inhibit or invert the output when a sequence of similar bits occurs - the first LFSR uses a conventional primitive polynomial, and the feed the output of the first into the second. The second shift register is shorter, doesn't have a primitive polynomial. Instead it is tapped to invert the output if all its bits are the same, so no run can exceed the size of the second shift register.

当出现类似位序列时,应该可以链接两个LFSR来禁止或反转输出 - 第一个LFSR使用传统的本原多项式,并将第一个LFSR的输出馈送到第二个。第二个移位寄存器较短,没有原始多项式。相反,如果输出的所有位都相同,则会对其进行抽头反转,因此没有运行可以超过第二个移位寄存器的大小。

Obviously this destroys the randomness of the output - if you have N bits in a row, the next bit is completely predictable. Messing around with using the output of another random source to determine whether or not to invert the output would defeat the second shift register - you wouldn't be able to detect the difference between that and just one random source.

显然这会破坏输出的随机性 - 如果连续有N位,则下一位是完全可预测的。使用另一个随机源的输出来判断是否反转输出会使第二个移位寄存器失败 - 你将无法检测到它与一个随机源之间的差异。

#10


Check out the GSL. I believe it has some functions that do just what you want. They at least are guaranteed to be random bit strings. I'm not sure if they would LOOK random, since thats more of a psychological question.

查看GSL。我相信它有一些功能可以满足您的需求。它们至少保证是随机位串。我不确定他们是否会随意,因为这更像是一个心理问题。

#11


Can't believe nobody mentioned this: If you want a longest run (period) of 2N repeats:

不敢相信没人提到这个:如果你想要2N重复的最长运行(期间):

PeopleRandom()
{
    while(1)
    {
        Number = randomN_bitNumber();
        if(Number && Number != MaxN_BitNumber)
            return Number;
    }
}

this gives much better results in terms of amount of tosses than using a 32-bit, etc rand

与使用32位等兰特相比,这在投掷量方面提供了更好的结果

pros:

  • you only toss values 2/2^N of the time.
  • 你只能投掷2/2 ^ N的时间。

  • larger N give better results.
  • N越大,效果越好。

Since the number of values that do not split the value with a 1 in the middle bit is exactly half, you can go with a larger N than you otherwise would have if you can tolerate a larger largest run less than half the time.

由于在中间位中没有将值拆分为1的值的数量恰好是一半,因此如果您可以容忍较大的最大运行时间少于一半,则可以使用比您更大的N.

#12


One simple approach would be to generate one bit at a time, with a tuning parameter to control the probability that each new bit matches the previous one. By setting the probability below 0.5, you can generate sequences that are less likely to contain long runs of repeating bits (and you can tune that likelihood). Setting p = 0 gives a repeating 1010101010101010 sequence; setting p = 1 gives a sequence of all 0s or all 1s.

一种简单的方法是一次生成一个比特,使用调整参数来控制每个新比特与前一个比特匹配的概率。通过将概率设置为低于0.5,您可以生成不太可能包含长行重复位的序列(并且您可以调整该可能性)。设置p = 0给出重复的1010101010101010序列;设置p = 1给出全0或全1的序列。

Here is some C# to demonstrate:

这是一些C#来演示:

double p = 0.3; // 0 <= p <= 1, probability of duplicating a bit

var r = new Random();
int bit = r.Next(2);    

for (int i = 0; i <100; i++)
{
    if (r.NextDouble() > p)
    {
        bit = (bit + 1) % 2;
    }        

    Console.Write(bit);                
}

This might well be too slow for your needs, since you need to generate a random double in order to obtain each new random bit. You could, instead, generate a random byte and use each pair of bits to generate the new bit (i.e. if both are zero then keep the same bit, otherwise flip it, if you're happy with the equivalent of a fixed p = 0.25).

这可能对您的需求来说太慢,因为您需要生成随机双精度才能获得每个新的随机位。相反,您可以生成一个随机字节并使用每对位来生成新位(即如果两者都为零则保持相同的位,否则将其翻转,如果您对等效的固定p = 0.25感到满意)。

Furthermore, it's still possible to get long sequences of repeated bits, you've just lowered the probability of doing so.

此外,它仍然可以获得长序列的重复位,你只是降低了这样做的可能性。


推荐阅读
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
author-avatar
tlgcc
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有