如何制作一个一次接受一个值的排列函数?

2024-03-02

我正在寻找一个函数,它接受区间 0,1....N 中的 1 个数字,并返回同一区间中的排列值。

0、1、2、3、4、5 和 f(x) 的示例如下:

f(0)=5;
f(1)=1;
f(2)=0;
f(3)=4;
f(4)=2;
f(5)=3;

根据我的研究/理解,这是一个循环群,其中 f(x) 是它的全部基础。 但是,如果发现函数 f(x) = 911 * x % N 是我想要的示例,那么在使用它时会出现模式。 911 是一个很大的素数,通过改变它,我得到了另一种排列,但仍然出现了一些问题。我的愿望是结果是随机的。

我知道我可以使用 [ 0, 1, 2...N ].shuffle() 之类的东西预先生成排列,但就我而言,我不能这样做。

我有一项服务需要输入一个数值并返回排列后的值/位置。 N 设置在服务器端,这也是我正在寻找的功能。


请记住,我在这里描述的算法基于列表 [1, 2, ... N-1] (长度为 N-1)。如果您坚持使用列表 [0, 1, ..., N](长度为 N+1),请进行所需的细微修改。此外,为了简洁起见,我使用 % 操作数的方式与大多数编程语言略有不同:a % b 取 1 和 b 之间的值,而不是 0 和 b - 1 之间的值,但背后的主要思想当然没有改变,因此 a % b 的值为 1 和 b 之间的整数,与 a 模 b 一致。

如果您仔细阅读本文,您会很明显地发现,生成的随机播放根本不是随机的。然而,如果参数选择得当,模式将不容易识别(我的模幂运算的基本思想来自密码学,其中具有不可识别的模式和不可恢复的函数非常重要)。

这更多的是与语言无关的算法描述,而不是实际的编程解决方案。我不会详细介绍有效实施和您可能遇到的陷阱。我希望它仍然有帮助。我还在 python 中编写了其中的某些部分,因此我可以提供进一步的帮助,甚至在需要时分享我的代码,但这之前需要一些完成和重构。

使用求幂代替乘法来消除模式

您对 f(x) = t * x % N(您选择为 911)的初步尝试显示了一些模式,因为乘法保持线性(在它的“模数”含义中)。

如果您使用幂而不是乘法,您可以给人更多随机的感觉。像 f(x) = t ^ x % N 之类的东西。但是,必须明智地选择 t(就像在乘法情况下一样,成为 N 的互质),并且此公式给出的输出不会提供不同的结果仅在 N 为素数的情况下,不同 x 值的数字。

大学数学即将到来,请耐心等待,我会尽量保持简单。

我们需要使用原根。相关的维基百科文章 http://en.wikipedia.org/wiki/Primitive_root_modulo_n可能会有很大帮助,但基本思想是精心选择的基数的幂的余数取 1 到 N-1 之间的所有值。例如

3^1 = 3
3^2 = 9 = 2 (mod 7)
3^3 = 27 = 6 (mod 7)
3^4 = 81 = 4 (mod 7)
3^5 = 243 = 5 (mod 7)
3^6 = 729 = 1 (mod 7)

都是不同的(从这一点开始,这些值从头开始重复:3^7 = 3^1 (mod 7)、3^8 = 3^2 (mod 7),依此类推)。

所以,如果你的 N 是 7,那么 3 就可以很好地成为 t。对于 1 到 6 之间的 x 值,可以使用 f(x) = (3 ^ x) % 7。

这会产生以下 f:

f(1) = 3
f(2) = 2
f(3) = 6
f(4) = 4
f(5) = 5
f(6) = 1

引入转变,提供一些额外的随机效果

如果你稍微玩一下这个,你会注意到,N-1 总是被打乱为 1。如果你想避免这种情况,我们可以更进一步,选择一个任意数字 k 在求幂后添加。也就是说,使用 g(x) = (f(x) + k) % (N-1) = ((t ^ x) % N + k) % (N-1),在我们的示例中令 k 为 2,产生排列:

g(1) = 5
g(2) = 4
g(3) = 2
g(4) = 6
g(5) = 1
g(6) = 3

如何选择底座

现在你有了基本的感觉。但当 N 不是 7 时,一般如何使用呢?

问题的关键是选择参数 t,在我们的示例中为 3。

不幸的是,这通常是一个难题(数学家称之为寻找原根 https://math.stackexchange.com/questions/124408/finding-a-primitive-root-of-a-prime-number),据我所知,没有任何易于解释的开箱即用的解决方案。

但这只是问题的一部分。更可悲的是,如果 N 是合数,原根甚至不起作用。例如,如果 N=6,则不存在任何数字 t 的表达式 t^x modulo 6 取 1 到 5 之间的所有值。

不过解决这部分并不是太难。

复合 N 可以做什么

如果 N 是合数,我们应该找到一个稍大一点的质数 P,并以基于该质数的算法为基础,通过将越界数字替换为洗牌后的值(并在需要时进行迭代) 。

例如,如果 N 为 6,我们可以选择 P 为 7,并使用之前构造的 g(x)。

g(1) = 5 ok (5<=N-1 holds)                          h(1) = 5
g(2) = 4 ok                                         h(2) = 4
g(3) = 2 ok                                    =>   h(3) = 2
g(4) = 6 too large, using g(g(4)) = g(6) = 3        h(4) = 3
g(5) = 1 ok                                         h(5) = 1

为了安全起见,我给出了另一个 N=4 的例子,其中我们使用之前计算的 P=7 的解决方案。

g(1) = 5, g(5) = 1                                  h(1) = 1
g(2) = 4, g(4) = 6, g(6) = 3                   =>   h(2) = 3
g(3) = 2                                            h(3) = 2

现在应该清楚了。选择接近 N 的 P 是明智的,这样 g 的越界值就不需要进行太多的重新计算。

回到寻找t

所以我们剩下的唯一问题就是找到可以用作幂运算底数的原根。

如果我之前链接的页面上的数学引起了一些本能的厌恶,我有一些好消息给你:t 的可能好的值在区间 [2, N-1] 中是密集的,所以即使是随机猜测也可能有所帮助。

有一些详细信息如何有效地验证随机选择的 t 是否真的对链接页面上的我们有利,但除非您正在处理非常大的数字,否则您可以只进行求幂并检查数字 1 是否出现早于 ( t 的 N-1) 次方(也许您还记得我注意到 t^x=1 (mod N) 在 x=N-1 的情况下始终成立,因此 1 的较早出现会破坏唯一性)。

我建议在 N/2 左右寻找合适的 t(意味着数量级 - 对于 P=91367,t=54949 效果很好)。如果您选择的 t 太低(例如 t=2),您可以轻松发现由某些相邻 x 值求幂引起的模式(2+k、4+k、8+k...将出现在彼此)。如果 t 太接近 N,则在相同奇偶校验的连续 x 值中查看 f(x) 时,可能会出现类似的现象。 t 的一个好的选择应该涵盖这些模式,并以足够随机的结果结束。

Summary

再次,这是算法的步骤

(N 给定)

找到一个比 N 稍大的素数 P

选择 1 和 P-1 之间的任意数字 k

找到 t,它是 P 的原根

(对于给定的 x,输出随机 h(x) 是)

计算

f(x) = (t ^ x) % P

计算

g(x) = (f(x) + k) % (P-1)

计算

h(x) = g(x)                                       if g(x)<=N-1,
       iterate the calculations with x = g(x)     otherwise
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何制作一个一次接受一个值的排列函数? 的相关文章

  • 为什么 Math.Round 不返回 int? [复制]

    这个问题在这里已经有答案了 在 C 中 为什么舍入数学函数 Floor Ceiling 和 Round 不返回int 考虑到函数的结果始终是整数 为什么它返回一个float double or decimal double has the
  • Lua 的标准(或最好支持的)大数(任意精度)库是什么?

    我正在处理大量无法四舍五入的数字 使用 Lua 的标准数学库 似乎没有方便的方法来保持精度超过某些内部限制 我还看到有几个库可以加载以处理大数字 http oss digirati com br luabignum http oss dig
  • 小数纬度/经度的最大长度 度?

    地球表面一度纬度和经度的最大长度是多少 以公里或英里为单位 但请注明 我不确定我是否说得足够清楚 让我重新表述一下 众所周知 地球不是一个完美的圆 赤道 或厄瓜多尔 纬度 经度变化 1 0 可能意味着一个距离 而两极的相同变化可能意味着另一
  • 哪种编程语言或库可以处理无限级数?

    哪种编程语言或库能够处理无限级数 例如几何级数或调和级数 它可能必须有一些众所周知的系列的数据库 并在收敛的情况下自动给出适当的值 并且可能在发散的情况下生成异常 例如 在 Python 中 它可能如下所示 sum 0 sign 1 0 f
  • Math.Sin、Math.Cos 和 Math.Tan 精度以及正确显示它们的方法

    我正在用 C 编写一个计算器 textBoxResult是一个文本框 我在其中显示数字 recount是以度为单位获取角度并以弧度为单位返回的函数 我的角度是从texBoxInput public double recount int nu
  • 从数字列表中生成所有唯一对,n 选择 2

    我有一个元素列表 假设是整数 我需要进行所有可能的两对比较 我的方法是 O n 2 我想知道是否有更快的方法 这是我在java中的实现 public class Pair public int x y public Pair int x i
  • 为什么 Math.Atan(Math.Tan(x)) != x?

    如果 tan x y 并且 atan y x 为什么 Math Atan Math Tan x x 我正在尝试计算 x 例如 tan 2 x 3 5 so atan tan 2 x 3 atan 5 等等 但我已经尝试过 double d
  • 如何在sphinx中启用数学?

    我在用sphinx http sphinx pocoo org index html与pngmath http sphinx pocoo org ext math html module sphinx ext pngmath扩展来记录我的代
  • 如何将数学公式转换为Python代码?

    有没有简单的方法可以将数学公式转换为 Python 代码 也许是译者 网络参考 具体的书籍章节 任何东西 对于正则表达式 有诸如Kodos http kodos sourceforge net 和网站 例如pythonregex com h
  • 在 3d 空间中的两个平面之间进行插值

    我正在开发一种工具 可以让您在 3D 体积 上圈出 包围事物 我想通过标记 切片 1 和 3 并从该信息 填充 切片 2 来节省时间 两个简单的解决方案是 1 slice2 slice1 AND slice3 gets the overla
  • 限制纬度和经度值的模数

    我有代表纬度和经度的双精度数 我可以轻松地将经度限制为 180 0 180 0 具有以下功能 double limitLon double lon return fmod lon 180 0 360 0 180 0 这是有效的 因为一端是排
  • 为什么斐波那契堆被称为斐波那契堆?

    The 斐波那契堆 http en wikipedia org wiki Fibonacci heap数据结构的名称中有 斐波那契 一词 但数据结构中似乎没有任何内容使用斐波那契数 根据维基百科文章 斐波那契堆的名称来自于运行时间分析中使用
  • 构建协同过滤/推荐系统

    我正在设计一个网站 该网站的概念是根据用户的口味向他们推荐各种商品 即他们评价过的项目 添加到收藏夹列表中的项目等 亚马逊 Movielens 和 Netflix 就是这样的例子 现在 我的问题是 我不知道从哪里开始了解这个系统的数学部分
  • 有没有办法根据值是大于 0.5 还是小于 0.5 来进行下限/上限?

    我正在尝试舍入我的价值观 以便如果它是0 5或更大 则变为1 否则就变成0 例如 3 7 gt 4 1 3 gt 1 2 5 gt 3 有任何想法吗 Math Round 3 7 MidpointRounding AwayFromZero
  • 使用矩阵代数来操作字符串:可行吗?

    我正在尝试使用矩阵代数来操作字符串 这意味着能够使用字符串或字符串数 组的串联和粘贴来实现多个类似矩阵的结构 我之前尝试在 R 上实现这个东西 但这是不可能的 因为矩阵只能有一维条目 我希望足够的与语言无关和抽象 但为了清楚起见 我将使用类
  • 判断一个点是否在直角三角形内

    我一直想知道最简单的方法来确定一个点是否位于三角形内 或者在这种情况下 判断一个点是否位于对角线切成两半的矩形内 假设我有一个 64x64 像素的矩形 对于这个矩形 如果传递的点位于矩形的左上角 我想返回 TRUE 值 否则返回 FALSE
  • 正则表达式匹配不可约分数

    我怎样才能匹配不可约分数 http en wikipedia org wiki Irreducible fraction用正则表达式 例如 23 25 3 4 5 2 100 101 等 首先 我不知道正则表达式中的gcd算法实现 Upda
  • 简单的jquery求和

    我有未知数量的输入字段 有 add 类 我只想用 jquery 对这些进行求和 不知道我错在哪里
  • Math.random() 在 JavaScript 中如何工作?

    我最近想出了如何通过谷歌获取随机数 这让我思考如何Math random 工作 所以我在这里我无法弄清楚他们是如何做到 Math random 的 除非他们使用了类似时间的东西 有谁知道 JavaScript 是如何做到的吗 Math ra
  • 计算二维笛卡尔坐标中不规则形状的边界

    我正在寻找一种计算不规则形状边界的解决方案 Lats take a look at Square example 如果我有Minimum x and y and Maximum x and y like MaxX 5 MinX 1 MaxY

随机推荐