有没有一种方法可以生成哈希函数,该哈希函数返回长签名类型的哈希码?

时间:2020-10-05 07:30:01

标签: c++ c++11 hash long-integer

我需要一个函数,该函数可以将字符串作为输入并从中生成哈希码。当前,在c ++中,我们有std :: hash来做到这一点,但这会返回size_t(unsigned long long)类型的哈希码。在这里,我需要一个哈希函数,该函数可以为我提供长久签名的哈希码。

我也尝试过使用模数运算符,但这给了我负值,并且这些值不可靠。因此,请给我有关我可以在C ++中使用的哈希函数的建议,这样我就可以得到长签名的哈希码。

1 个答案:

答案 0 :(得分:0)

我需要一个哈希函数,该函数可以为我提供signed long long类型的哈希码。

您可以将最高有效位设置为0,除非您的体系结构内部具有整数类型的怪异表示,否则当转换为相同大小的带符号类型时,它将产生一个正数。

template <class S>
constexpr size_t clamp_to_positive(size_t value)
{
    return value & (std::numeric_limits<size_t>::max() >> 
        (std::numeric_limits<size_t>::digits - std::numeric_limits<S>::digits)
    );
}

然后您可以将其命名为

auto my_hash = clamp_to_positive<long long>(std::hash<std::string>{}(source_string));

不过,如Ben Voigt所述,最简单的方法是将无符号值右移一位。

auto my_hash = static_cast<long long>(std::hash<std::string>{}(source_string) >> 1);

解决此问题的另一种方法是强制取模操作始终返回正值。

// Evaluates abs(x) as an unsigned type, avoiding corner case overflow.
template <class T>
constexpr auto unsigned_abs(T x)
{
    static_assert(std::is_integral_v<T>);
    if constexpr ( std::is_unsigned_v<T> ) {
        return x;
    }
    return x < 0
        ? ~static_cast<std::make_unsigned_t<T>>(x) + 1 
        : static_cast<std::make_unsigned_t<T>>(x);
}

// Evaluates abs(x) % abs(y) avoiding overflows. The result has the same type
// of y and it's always   0 <= result < y. It has UB when y == 0.
template <class X, class Y> 
auto absolute_remainder(X x, Y y)
{
    static_assert( std::is_integral_v<X> && std::is_integral_v<Y> );
    return static_cast<Y>(unsigned_abs(x) % unsigned_abs(y));
}

您是否真的需要其中之一,或者可能需要对程序的当前设计进行更改来找出答案。