【问题标题】:A function where small changes in input always result in large changes in output输入的小变化总是导致输出大变化的函数
【发布时间】:2011-03-03 21:06:05
【问题描述】:

我想要一个函数的算法,它接受 n 个整数并返回一个整数。对于输入的微小变化,得到的整数应该变化很大。尽管我参加了许多数学课程,但我并没有太多地使用这些知识,现在我需要一些帮助......

这个函数的一个重要属性应该是,如果它与坐标对一起使用作为输入并且结果被绘制在图像上(例如作为灰度值),任何重复图案应该只有在图像非常大。

我尝试了各种伪随机数算法,但收效甚微,最后令我震惊的是,md5 几乎符合我的标准,只是它不适用于数字(至少据我所知不是)。这导致了类似于这个 Python 原型的东西(对于 n = 2,它可以很容易地更改为采用整数列表):

import hashlib
def uniqnum(x, y):
    return int(hashlib.md5(str(x) + ',' + str(y)).hexdigest()[-6:], 16)

但是当输入和输出都是整数时,显然遍历字符串是错误的。什么是这个实现的好替代品(在伪代码、python 或任何语言中)?

【问题讨论】:

    标签: algorithm math function numbers random


    【解决方案1】:

    “哈希”是为完全解决您所描述的问题而创建的解决方案。见wikipedia's article

    你使用的任何散列函数都会很好;哈希函数倾向于根据这些标准来判断:

    • 它们防止冲突(两个单独的输入产生相同的输出)的程度——其副产品是函数最小化可能永远无法达到的输出的程度输入。
    • 在给定一组均匀分布的输入的情况下,其输出分布的均匀性
    • 输入中的微小变化在输出中产生巨大变化的程度。

    (见perfect hash function

    考虑到创建一个最大化所有这些标准的哈希函数是多么困难,为什么不直接使用最常用和最依赖的现有哈希函数之一呢?

    从表面上看,将整数转换为字符串几乎就像是另一层加密! (我认为这对您的目的有好处)

    但是,您的问题要求使用专门处理数字的哈希函数,所以我们开始吧。


    对整数起作用的哈希函数

    如果你想借用已有的算法,你可能想涉足pseudo-random number generators

    一种简单的方法是中方法:

    • 取一个数字
    • 平方
    • 剪掉数字,让中间的数字与原来的长度相同。

    即,

    1111 => 01234321 => 2342
    

    因此,在中间平方方法中,1111 将被“散列”为 2342。

    这种方式不是那么有效,但是对于少量的哈希,它具有非常低的冲突率、均匀分布和很大的混乱可能性(小的变化 => 大的变化) .但是如果你有很多价值观,那么是时候寻找其他东西了......

    所有可行高效且简单的随机数生成器的祖父是 (Mersenne Twister)[http://en.wikipedia.org/wiki/Mersenne_twister]。事实上,每一种可以想象的编程语言都可能有一个实现。您的哈希“输入”在他们的术语中称为“种子”。

    总结

    1. 基于字符串的哈希函数没有错
    2. 如果您想坚持使用整数并喜欢它,请尝试使用您的数字作为伪随机数生成器的种子。

    【讨论】:

    • 这是一个很好的答案,但是:我的一次不成功的尝试是使用 Mersenne Twister,所以我认为我需要的是一个实际的示例实现,伪代码是好的。自从我尝试这个以来已经至少一年(可能更多),所以我不记得我的问题到底是什么。
    • 糟糕,我没有注意到您在问题中特别提到了尝试伪随机数。我现在觉得有点傻。无论如何,您有什么理由尝试从头开始编写 Mersenne,而不是使用预先存在的库?你用什么语言工作?
    • 查看 Pete Kirkham 对 Bob Jenkins 的 Mix 函数的回答;看起来你可以使用。
    • @mstksg:当我查看维基百科页面上的代码时,我看到一些东西需要一个种子,然后可以生成一个又一个数字。这是否可以简单地转换为函数 fun(n0, n1, ...) -> x?
    • 回答你上面重写的问题:我不需要从头开始创建它,但我需要它来适应我想要的签名。
    【解决方案2】:

    散列完全符合您的要求。如果您真的不想使用字符串,请找到一个可以接收数字或二进制数据的 Hash 库。但是在这里使用字符串对我来说看起来不错。

    【讨论】:

      【解决方案3】:

      Bob Jenkins' mix function 是一个经典的选择,在 n=3 时。

      【讨论】:

      • 我只是简单地扫描了文本,所以:它是否仅限于 n = 3?它说的是“键是未对齐的可变长度字节数组”,这似乎表明可以使用任何 n。
      • 您可以使用 mix 来增加大量数字的简单哈希结果之间的距离,或者直接在三个数字上使用它。
      【解决方案4】:

      正如其他人指出的那样,哈希函数完全符合您的要求。散列采用字节——不是字符串——并返回字节,整数和字节之间的转换当然很简单。这是一个适用于 32 位整数并输出 32 位整数的示例 Python 函数:

      import hashlib
      import struct
      
      def intsha1(ints):
        input = struct.pack('>%di' % len(ints), *ints)
        output = hashlib.sha1(input).digest()
        return struct.unpack('>i', output[:4])
      

      当然,它可以很容易地适应不同长度的输入和输出。

      【讨论】:

        【解决方案5】:

        看看这个,也许你会受到启发

        Chaotic system

        在混沌动力学中,微小的变化会产生很大的差异。

        【讨论】:

        • 谢谢,但我正在寻找更多的实际算法。
        【解决方案6】:

        x 位分组密码将采用一个数字并将其有效地转换为另一个数字。您可以组合(总和/多?)您的输入数字并对其进行加密,或者对每个数字进行迭代加密 - 类似于 CBC 或链式模式。谷歌“格式保留加密”。可以创建 32 位分组密码(不是广泛“可用”)并使用它来创建“散列”输出。哈希和加密的主要区别在于哈希是不可逆的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-11-21
          • 2021-08-07
          • 2018-11-21
          • 1970-01-01
          • 1970-01-01
          • 2018-01-14
          • 1970-01-01
          相关资源
          最近更新 更多