输入中的微小变化总是导致输出变化很大的函数

时间:2010-06-15 08:17:41

标签: algorithm math function numbers random

我想要一个函数的算法,它取n个整数并返回一个整数。对于输入中的微小变化,结果整数应该有很大差异。尽管我已经学了很多数学课程,但我还没有那么多地使用这些知识,现在我需要一些帮助......

此函数的一个重要属性应该是,如果它与坐标对一起用作输入并且在图像上绘制结果(例如,作为灰度值),则任何重复模式应该仅在图像非常可见时才可见大。

我已经尝试了各种伪随机数算法,但收效甚微,最后让我觉得md5几乎符合我的标准,除了它不是数字(至少不是我所知道的)。这导致类似这样的Python原型(对于n = 2,当然可以很容易地将其更改为采用整数列表):

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

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

6 个答案:

答案 0 :(得分:8)

“哈希”是为解决完全您正在描述的问题而创建的解决方案。见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. 如果你想坚持使用整数并且想要使用,请尝试使用你的数字作为伪随机数生成器的种子。

答案 1 :(得分:4)

Hashing完全符合您的要求。如果您真的不想使用字符串,请找一个可以获取数字或二进制数据的Hash库。但是在这里使用字符串看起来不错。

答案 2 :(得分:3)

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

答案 3 :(得分:1)

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

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])

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

答案 4 :(得分:0)

看看这个,可能是你可以受到启发

Chaotic system

在混沌动力学中,小的变化会大大改变结果。

答案 5 :(得分:0)

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