我想要以下机制:
int64_t MyHash (const std::string& value);
std::string
(通常为100字节)作为输入-2<sup>53</sup> to 2<sup>53</sup>-1
范围内我尝试使用std::hash()
;问题是:在每个平台上都不同。不仅如此,每次运行都会有所不同。
当前,使用Qt
的{{1}}得到了QCryptographicHash
校验和,并且我将其截断为64位。即使在这种截断中,碰撞的可能性也会增加。
无论如何,我的目标是在54位内获得该值。一种明显的解决方案是将该数字除以2048。
问题:是否有更好的解决方案来获取54位哈希值?
Javascript解决方案也很好。
目的:该值传递给Javascript。现在,它的数据类型SHA256
可以容纳64位double,即54位。
答案 0 :(得分:2)
获取54位哈希值,您可能会为了速度而牺牲质量。在SHA256中,最低的54位将以合理的可能度提供尽可能可靠的散列,但代价不是最佳性能。
其他可能性是64位CRC,可以通过快速的Google搜索轻松找到。这可能会更快,但对于任何合理的用例来说仍然可以。
对于截断到[-2 53 .. 2 53 -1]范围,我只使用带有合适位掩码的&
,然后减去2 53 。
2 53 是0x20000000000000,所以它就是:
crc = crc-0x20000000000000LL;
对于64位CRC本身,以下代码直接取自http://andrewl.dreamhosters.com/filedump/crc64.cpp,这是一个可下载的.cpp文件。原始文件是使用Windows数据类型编写的,在这里我已将其转换为普通的stdint.h
类型。
unit64_t const poly = 0xC96C5795D7870F42ULL;
uint64_t table[256];
void generate_table()
{
for(int i = 0; i < 256; ++i)
{
uint64_t crc = i;
for(int j = 0; j < 8; ++j)
{
if(crc & 1)
{
crc >>= 1;
crc ^= poly;
}
else
{
crc >>= 1;
}
}
table[i] = crc;
}
}
您将希望在程序启动时仅调用一次generate_table()
。要么,要么运行在一个很小的工具中,它会打印出结果,并使用这些值直接初始化表。
要实际评估crc,请将字节序列和长度传递给它:
uint64_t calculate_crc(uint8_t *stream, size_t n)
{
uint64_t crc = 0;
for(size_t i = 0; i < n; ++i)
{
uint8_t index = stream[i] ^ crc;
uint64_t lookup = table[index];
crc >>= 8;
crc ^= lookup;
}
return crc;
}
根据您的好奇程度,可能值得看一下链接源,其中有大量注释可以解释发生了什么情况。