我需要一个函数,该函数可以将字符串作为输入并从中生成哈希码。当前,在c ++中,我们有std :: hash来做到这一点,但这会返回size_t(unsigned long long)类型的哈希码。在这里,我需要一个哈希函数,该函数可以为我提供长久签名的哈希码。
我也尝试过使用模数运算符,但这给了我负值,并且这些值不可靠。因此,请给我有关我可以在C ++中使用的哈希函数的建议,这样我就可以得到长签名的哈希码。
答案 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));
}
您是否真的需要其中之一,或者可能需要对程序的当前设计进行更改来找出答案。