Algorithm 是否有一个函数接受两个值,让f(x,y)=f(y,x),并且输出是唯一的?
我想知道是否有一种方法可以基于两个实体之间的关系生成一个键,使关系a->b的键与关系b->a的键相同 理想情况下,这将是一个哈希函数,它接受任何一个关系成员,但不管成员的显示顺序如何,都会生成相同的输出 显然,你可以用数字来做这件事(例如,加法(2,3)相当于加法(3,2))。我的问题是,我不想让加法(1,4)等于加法(2,3)。显然,任何哈希函数都有重叠,但我的意思是唯一性的感觉很弱 我天真的(也是不受欢迎的)想法是:Algorithm 是否有一个函数接受两个值,让f(x,y)=f(y,x),并且输出是唯一的?,algorithm,language-agnostic,encryption,hash,Algorithm,Language Agnostic,Encryption,Hash,我想知道是否有一种方法可以基于两个实体之间的关系生成一个键,使关系a->b的键与关系b->a的键相同 理想情况下,这将是一个哈希函数,它接受任何一个关系成员,但不管成员的显示顺序如何,都会生成相同的输出 显然,你可以用数字来做这件事(例如,加法(2,3)相当于加法(3,2))。我的问题是,我不想让加法(1,4)等于加法(2,3)。显然,任何哈希函数都有重叠,但我的意思是唯一性的感觉很弱 我天真的(也是不受欢迎的)想法是: function orderIndifferentHash(string
function orderIndifferentHash(string val1, string val2)
{
return stringMerge(hash(val1), hash(val2));
/* String merge will 'add' each character (with wrapping).
The pre-hash is to lengthen strings to at least 32 characters */
}
在函数
orderInferenceThash
中,您可以首先按照某些条件对val1
和val2
进行排序,然后应用任何希望得到结果的哈希函数
function orderIndifferentHash( val1, val2 ) {
if( val1 < val2 ) {
first = val1
second = val2
}
else {
first = val2
second = val1
}
hashInput = concat( first, second )
return someHash( hashInput )
// or as an alternative:
// return concat( someHash( first ), someHash( second ) )
}
函数顺序无差异(val1,val2){
if(val1
您的目标是:
一些函数f(x,y)
使得
f(x,y)==f(y,x)
和f(x,y)!=f(a,b)=>(x==a
)或(y==b
和x==b
)y==a
(x,y)
u(a)
分别应用于x
和y
(其中u(a)=u(b)
意味着a==b
,并且u(a)
的长度是恒定的)u(x)
和u(y)
x==y
,那么这两个哈希值基本相同,因此不会失去一般性x
,因此:
f(y,x)=u(x)+u(y)=f(x,y)
f(x,y)==f(a,b)
,这意味着:
和u(x)==u(a)
=>u(y)==u(b)
和x==a
,或y==b
和u(y)==u(a)
=>u(x)==u(b)
和y==a
x==b
对x和y进行排序,然后在结果哈希长度不变的情况下应用任何哈希函数。对于数字,一种实现方法是对两个数字
x
和y
取第x个素数和第y个素数,并计算这些素数的乘积。这样,您将保证每个不同的x
和y
对的乘积的唯一性,并且独立于参数顺序。当然,为了以实际有意义的效率做到这一点,您需要为x
和y
的所有可能值保留一个素数表。如果从相对较小的范围中选择x
和y
,这将起作用。但是如果范围很大,表本身就变得不切实际,您将别无选择,只能接受一些冲突概率(比如保留一个大小合理的N素数表,并为给定的x
选择x%N次素数)
其他答案中已经提到的另一种解决方案是构建一个完美的哈希函数,该函数对x
和y
值起作用,然后简单地将x
和y
的哈希连接起来。订单独立性是通过预排序x
和y
实现的。当然,构建一个完美的散列只能用于一组范围相当小的参数
有些事情告诉我,基于素数的方法将为您提供满足所需条件的尽可能短的哈希。不,不是真的。假设您有任何散列
h(x,y)
。然后定义f(x,y)=h(x,y)+h(y,x)
。现在有了一个对称散列
(如果你做一个简单的乘法“散列”,那么1+3和2+2可能会散列到相同的值,但即使是像h(x,y)=x*y*y这样的东西也可以避免——只要确保散列函数的至少一个参数中存在一些非线性。)是的,但只有当
u
是一个完美的散列函数,即u(a)==u(b)时,这才是真的
相当于a==b
。Duh…排序。。。我现在觉得自己很愚蠢——只要这两个值是可排序的,我们就可以按照相同的顺序进行散列。你能解释一下你所说的=>
是什么意思吗?我假设“除非”(假设你说的是f(x,y)!=f(a,b)=>(x==a和y==b…)
但我习惯于把它看作“因此”(正如你在底部使用的那样)。关于接受哪一个很难,另一个是第一个,完美地回答了这个问题,但这个答案更明确,背后有各种假设/想法(一旦你计算出排序,这一切都是显而易见的)。@Kragen:我不会将这两个散列连在一起(如果结果是数字的话,这甚至是不可能的),我宁愿将它们组合起来。有关组合的示例,请参见boost::hash_combine
:如果在哈希后进行连接,则会引入一些潜在的漏洞(取决于您对结果的处理)。例如,如果我看到两个输出f(x1,y1)
和f(x2,y2)
有一个共同的前缀或后缀,那么我知道其中一个输入是共同的。好主意。不幸的是,性能会扼杀我的用例,但我喜欢这种总是让我感到惊讶的想法。如果你使用的数字“足够小”(比如,32位体系结构上的16位整数或64位体系结构上的32位整数),您只需将最低(最高)n位移到th