问题描述
我需要在 windows 和 linux 中计算一个大字符串的哈希值,并且两个操作系统的结果应该相同。
对于一个简单的测试代码,我使用 std::hash 为 windows 和 linux 获得了不同的哈希值。这是有道理的,因为每个编译器的 std::hash 的实际实现可能使用不同的算法。
这带来了一个问题:有没有办法使用标准库来实现这一点?
对我来说更直接的答案是实现我自己的哈希算法,所以它对两个操作系统都是一样的。但这似乎有点矫枉过正。我不想重新发明轮子。
解决方法
标准库中的哈希算法不是固定的,可能因平台/编译器而异。
但是您可以使用非常短且快速的 FNV1a 算法进行散列,只需几行代码即可实现,见下文。你可以阅读它here。
它会在所有机器上给出相同的结果。但是你必须修复参数集,32 位或 64 位(32 位参数在我的代码中被注释掉了)。
const products = [{title: 'apple-green',tags: [{colour: 'red',tagType: 'colour'}]},{title: 'orange',tags: [{colour: 'orange',{title: 'cherry',{title: 'pear',tags: [{colour: 'green',tagType: 'colour'}]}];
const includesAnyCase = (s,t) => s.toLowerCase().includes(t.toLowerCase());
const filterProducts = (products,searchTerm) =>
products.filter(product =>
includesAnyCase(product.title,searchTerm) ||
product.tags.some(tag => includesAnyCase(tag.colour,searchTerm))
)
;
console.log(filterProducts(products,"green"));
输出:
#include <iostream>
#include <string>
#include <cstdint>
inline uint64_t fnv1a(std::string const & text) {
// 32 bit params
// uint32_t constexpr fnv_prime = 16777619U;
// uint32_t constexpr fnv_offset_basis = 2166136261U;
// 64 bit params
uint64_t constexpr fnv_prime = 1099511628211ULL;
uint64_t constexpr fnv_offset_basis = 14695981039346656037ULL;
uint64_t hash = fnv_offset_basis;
for(auto c: text) {
hash ^= c;
hash *= fnv_prime;
}
return hash;
}
int main() {
std::cout << fnv1a("Hello,World!") << std::endl;
}
,
有没有办法使用标准库来实现这一点?
不,不仅使用标准库,因为使用的哈希算法未标准化。
我不想重新发明轮子。
很遗憾,您必须这样做。
然而,您可以尝试摆脱它们应该相同的要求。如果您无法在哈希命中后比较数据,则无论如何您都无法确定是否获得了真正的命中。
,你应该考虑一下这个要求是否有用。我听说 php 现在有一个散列实现,它故意在每次程序运行时给出不同的结果,而 Swift 肯定做了完全相同的事情。您不应存储或传输哈希码,也不应期望在两次运行程序时它们是相同的。