字符串的双向“哈希”

时间:2011-10-30 18:59:24

标签: c++ hash

我想从字符串生成int并能够生成它。 类似哈希函数但是双向函数。 我想在我的应用程序中使用int作为ID,但希望能够在记录或调试时将其转换回来。

像:

int id = IDProvider::getHash("NameOfMyObject");

object * a = createObject(id);

...

if(error)
{
    LOG(IDProvider::getOriginalString(a->getId()), "some message");
}

我听说过略微修改过的CRC32很快且100%可逆,但我找不到它,而且我自己也无法写。

任何提示我应该使用什么? 谢谢!

修改 我刚刚创建了源代码,我有完整的CRC32来源:

Jason Gregory:游戏引擎架构

报价:

"与任何散列系统一样,冲突是可能的(即,两个不同的字符串可能以相同的散列码结束)。但是,通过合适的散列函数,我们可以保证不会发生我们可能在游戏中使用的所有合理输入字符串的冲突。毕竟,32位散列代码表示超过40亿个可能的值。因此,如果我们的哈希函数在这个非常大的范围内很好地分配字符串,我们就不太可能发生冲突。在Naughty Dog,我们使用了CRC-32算法的变体来勾选我们的字符串,而且我们在Uncharted:Drake' Fortune的两年多的开发中并没有遇到过一次碰撞。"

6 个答案:

答案 0 :(得分:19)

将任意长度的字符串减少到固定大小的int在数学上是不可能反转的。见Pidgeonhole principle。有几乎无限量的字符串,但只有2 ^ 32 32位整数。

32位哈希(假设你的int是32位)可以很容易地发生冲突。所以它也不是一个好的唯一ID。

有一些哈希函数允许您使用预定义的哈希创建一条消息,但它很可能不是原始消息。这称为pre-image

对于你的问题,看起来最好的想法是创建一个将整数-id映射到字符串并返回的字典。


要在散列n个字符串时获得碰撞的可能性,请查看the birthday paradox。该上下文中最重要的属性是,一旦散列消息的数量接近可用散列值的数量的平方根,就可能发生冲突。因此,如果您对大约65000个字符串进行散列,则可能会发生32位整数冲突。但如果你运气不好,它可能会更早发生。

答案 1 :(得分:16)

我完全满足你的需要。它被称为“指针”。在此系统中,“指针”始终是唯一的,并且始终可用于恢复字符串。它可以“指向”任何长度的任何字符串。作为奖励,它也具有与你的int相同的大小。您可以使用&操作数获取字符串的“指针”,如我的示例代码所示:

#include <string>
int main() {
    std::string s = "Hai!";
    std::string* ptr = &s; // this is a pointer
    std::string copy = *ptr; // this retrieves the original string
    std::cout << copy; // prints "Hai!"
}

答案 2 :(得分:4)

您需要的是加密。哈希定义是一种方式。您可以尝试使用一些加/减值的简单XOR加密。

...还有更多来自谷歌搜索...

答案 3 :(得分:3)

你可以看一下完美的哈希

http://en.wikipedia.org/wiki/Perfect_hash_function

仅在预先知道所有潜在字符串时才有效。在实践中,您启用的是创建一个可以反向查找的有限范围“哈希”映射。

通常,[哈希码+哈希算法]永远不足以获得原始值。但是,使用完美哈希,冲突按定义排除,因此如果源(值列表)已知,则可以返回源值。 / p>

gperf是一个众所周知的古老程序,用于在c / c ++代码中生成完美的哈希值。确实存在更多(参见维基百科页面)

答案 4 :(得分:1)

是不可能的。根据定义,散列是不可返回的函数。

答案 5 :(得分:0)

每个人都提到,不可能有“可逆哈希”。但是,还有其他选择(例如加密)。

另一种方法是使用任何无损算法对字符串进行压缩/解压缩。

这是一种简单,完全可逆的方法,不会发生碰撞。