Мы используем несколько форм хеширования в проекте исследовательской базы данных. Например, для радикальной кластеризации, где мы используем N младшие биты для определения идентификатора кластера. Мы используем std::hash
для хеширования, что нам достаточно.
Однако, хотя мы знаем, что большинство реализаций используют идентичность для хеширования целых чисел, мы наткнулись на тот факт, что хеширование с плавающей запятой (имеет ли это смысл или нет, является другим обсуждением) по-разному реализуется на разных платформах.
Есть ли какие-то справедливые предположения, которые мы можем сделать относительно std::hash
?
MacOS:
clang version 6.0.1 (tags/RELEASE_601/final)
std::hash<float>{}(1.0f): 0000000000000000000000000000000000111111100000000000000000000000
std::hash<double>{}(1.0): 0011111111110000000000000000000000000000000000000000000000000000
Ubuntu:
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
std::hash<float>{}(1.0f): 0101001111100101011001010000100100010100111101010010111101001101
std::hash<double>{}(1.0): 0111010001100001101001000101000001001110110011100111101110011011
Единственные вещи, которые вы можете предположить, определены стандартом (см. cppreference).
Это означает:
В частности, они определяют operator () const, который:
Принимает один параметр типа Key.
Возвращает значение типа size_t, представляющее хеш-значение параметра.
Не выдает исключений при вызове.
Для двух одинаковых параметров k1 и k2 std :: hash () (k1) == std :: hash () (k2).
Для двух разных параметров k1 и k2, которые не равны, вероятность того, что std :: hash () (k1) == std :: hash () (k2) должна
быть очень маленьким, приближаясь к 1.0 / std :: numeric_limits :: max ().
Таким образом, вы можете иметь разные значения на разных платформах, на одной платформе с другой версией компилятора или даже от одного запуска к другому. В вашем случае кажется, что в одном случае вы можете использовать libc ++, а в другом — libstdc ++.
Других решений пока нет …