普通C语言中的快速随机洗牌函数

普通C语言中的快速随机洗牌函数,c,function,random,shuffle,C,Function,Random,Shuffle,多年来,我一直在思考这个问题,但从未实现过。我说的是一个快速、高效的C函数,它在输入端接受一个整数值(例如16位),在输出端给出一个完全不同的数字,并且具有相同的位大小,但是“考虑”了所有已经给出的数字,虽然不是通过使用实内存,而是通过数学魔术。对不起,英语不是我的母语,我的意思是函数应该随机一对一映射,但没有任何重复 我想象的可能的应用程序是,例如,一个像素交叉淡入淡出的图形例程,在这个例程中,你用一个像素一个像素地替换屏幕上的旧图片。坐标应随机选择,一旦像素被替换,就不应再次寻址(无重复)。

多年来,我一直在思考这个问题,但从未实现过。我说的是一个快速、高效的C函数,它在输入端接受一个整数值(例如16位),在输出端给出一个完全不同的数字,并且具有相同的位大小,但是“考虑”了所有已经给出的数字,虽然不是通过使用实内存,而是通过数学魔术。对不起,英语不是我的母语,我的意思是函数应该随机一对一映射,但没有任何重复

我想象的可能的应用程序是,例如,一个像素交叉淡入淡出的图形例程,在这个例程中,你用一个像素一个像素地替换屏幕上的旧图片。坐标应随机选择,一旦像素被替换,就不应再次寻址(无重复)。所有这些都是通过一个小型、快速、高效的基于数学的函数实现的(使用内存实现这一点很容易,但这不是我想要的)

显然,“稍微反转”的解决方案不会起作用,因为它看起来不会是随机的。甚至交换,例如第3位与第11位等。。为了制造更多的“混乱”,颠倒一些位,等等。。看起来不是很好,所以我正在寻找一个纯数学的,看起来非常随机的函数,可能至少有16位,并且使用尽可能少的内存(没有预计算表,因为我最终使用的第一个应用程序是在微控制器系统上,用公共域硬件和软件制作一个老式游戏)


您能帮忙吗?

先生,您非常需要一个哈希函数。例如,尝试a=(a*31)%0xffff;为了一个可怜的人

函数的
rand()
已经完成了这项工作。尽管如此,它不是从输入中获取数字,而是获取由
srand()
初始化并随每次调用
rand()
而更改的存储值

您可以查看
rand()
的实现来获取函数,也可以进一步研究

这里有一个提示:

首先,要了解什么是真正的

现在想象以下顺序:

m = 13
a = 7
b = 0

s = 5     s = (a*s + b) % m
s = 9     s = (a*s + b) % m
s = 11    s = (a*s + b) % m
s = 12    s = (a*s + b) % m
s = 6     s = (a*s + b) % m
s = 3     s = (a*s + b) % m
s = 8     s = (a*s + b) % m
s = 4     s = (a*s + b) % m
s = 2     s = (a*s + b) % m
s = 1     s = (a*s + b) % m
s = 7     s = (a*s + b) % m
s = 10    s = (a*s + b) % m
s = 5     s = (a*s + b) % m
请注意,在本例中,我设置了
b=0
,以便更容易地查找序列。尽管如此,这个例子并不是很好,但你可以理解其中的要点。对于给定的
m
,如果有一个很好的
a
b
选择,你可以得到看起来有点随机的数字


这样,您需要做的所有函数都是
(a*参数+b)%m

您要查找的基本上是一个组的循环生成器,该组与要交叉淡入淡出的像素数相对应。在最一般的情况下,这是任何与您的团队规模相关的互质。通过对像素数进行模化计算,可以获得随机性的外观,而不是实际的随机性

假设您有一个大小为32的域,并且从5个种子开始。通过不断地加上15的互质,你会得到

(5、20、3、18、1、16、31、14、29、12、27、10、25、8、23、4……)


对于您的需求来说,这似乎是随机的。

另一种选择是使用加密。由于加密是可逆的,所以每个加密都是唯一的。对于64位数字,使用DES。对于16或32位数字,请使用。您还可以根据任何所需的范围调整仓促布丁,而不仅仅是二次幂。

我不这么认为,也就是说,srand()可能有两个输入值,它们将返回相同的输出。另外,也许这是错误的,但我在某个地方读到,srand()在一个程序中只能被调用一次。@user1570761,我不是建议使用
rand
。我是说,您的功能类似于
rand
的工作方式。也就是说,您最有可能在网上找到rand的一个实现,并且您可以使其适应您的程序,即使其将算法应用于输入参数,而不是其全局变量。此外,使用
srand
中的不同值,您将从数字循环中的不同位置开始。因为这个循环覆盖了所有的数字(我的没有,但real
rand()
有),并且对任何数字都不重复,所以两个不同的输入不能得到相同的值。+1:听起来不错!现在OP如何找到他的域名大小的互质?@AAT:根据你的说法,你可以简单地使用
domain\u size/2-1
@wildplasser:和
9+15!=14
;)。更正了顺序。我同意这是一个更大的问题,特别是当“随机性”开始变得明显,对于小的共模。如果32位算术可用,最好选择一个加密值(或PRNG中使用的)对32位域的coprimes,例如线性同余生成器或经典Mersenne Twister中使用的coprimes。感谢所有编辑,我的心算不是以前的:)