微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用不同的编译器计算 std::hash

如何解决使用不同的编译器计算 std::hash

我需要在 windows 和 linux 中计算一个大字符串的哈希值,并且两个操作系统的结果应该相同。

对于一个简单的测试代码,我使用 std::hash 为 windows 和 linux 获得了不同的哈希值。这是有道理的,因为每个编译器的 std::hash 的实际实现可能使用不同的算法。

这带来了一个问题:有没有办法使用标准库来实现这一点?

对我来说更直接的答案是实现我自己的哈希算法,所以它对两个操作系统都是一样的。但这似乎有点矫枉过正。我不想重新发明轮子。

解决方法

标准库中的哈希算法不是固定的,可能因平台/编译器而异。

但是您可以使用非常短且快速的 FNV1a 算法进行散列,只需几行代码即可实现,见下文。你可以阅读它here

它会在所有机器上给出相同的结果。但是你必须修复参数集,32 位或 64 位(32 位参数在我的代码中被注释掉了)。

Try it online!

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 肯定做了完全相同的事情。您不应存储或传输哈希码,也不应期望在两次运行程序时它们是相同的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。