gpt4 book ai didi

C++:使用一对 (cpp_int, int) 整数作为 unordered_map 中的键(其中 cpp_int 是 boost 多精度整数)

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:07:19 27 4
gpt4 key购买 nike

对于我的无序 map ,我想使用 (cpp_int, int) 作为键对其中 cpp_intboost multiprecision整数:

#include <boost/multiprecision/cpp_int.hpp>
#include <unordered_map>

using boost::multiprecision::cpp_int;

std::unordered_map<std::pair<cpp_int, int>, double> myMap

在这个网站上搜索,我发现了很多关于为 std::pair<int,int> 使用自定义哈希函数的建议。作为键,但我找不到如何处理 std::pair<cpp_int, int> .

更新:为了澄清,我尝试了在网上找到的哈希函数(对于 (int,int)):

#include <boost/multiprecision/cpp_int.hpp>
#include <unordered_map>
using boost::multiprecision::cpp_int;
typedef std::pair<cpp_int, int> MyPair;

struct MyHash {
public:
size_t operator()(MyPair x) const throw() {
size_t h = x.first * 1 + x.second * 100000;
return h;
}
};

void function()
{
std::unordered_map<MyPair, double, MyHash> M;
}

这不编译:

error: cannot convert ‘boost::enable_if_c<true, boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_add, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, void, void, void>, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, int, void, void, void>, int, void> >::type {aka boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_add, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, void, void, void>, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, int, void, void, void>, int, void>}’ to ‘size_t {aka long unsigned int}’ in initialization
size_t h = x.first * 1 + x.second * 100000;
^

我的问题是:如何在 unordered_map 中使用成对的 (cpp_int,int) 作为键?

非常感谢您!

更新 2:感谢@sehe 将我指向 his answer (他在其中为 cpp_int 提供了一个哈希函数)。结合this answer (展示了如何将两个散列函数组合成一对),我提出了以下解决方案(它编译得很好,我需要测试我的问题以查看它是否有效):

#include <boost/archive/binary_oarchive.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_int/serialize.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>

#include <boost/functional/hash.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <unordered_map>


using boost::multiprecision::cpp_int;

typedef std::pair<cpp_int, int> MyPair;



namespace mp_hashing {
namespace io = boost::iostreams;

struct hash_sink {
hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}

typedef char char_type;
typedef io::sink_tag category;

std::streamsize write(const char* s, std::streamsize n) {
boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
return n;
}
private:
size_t* _ptr;
};

template <typename T> struct hash_impl {
size_t operator()(T const& v) const {
using namespace boost;
size_t seed = 0;
{
iostreams::stream<hash_sink> os(seed);
archive::binary_oarchive oa(os, archive::no_header | archive::no_codecvt);
oa << v;
}
return seed;
}
};
}

namespace std {
template <typename backend>
struct hash<boost::multiprecision::number<backend> >
: mp_hashing::hash_impl<boost::multiprecision::number<backend> >
{};
}


struct pair_hash {
template <class T1, class T2>
std::size_t operator () (const std::pair<T1,T2> &p) const {
auto h1 = std::hash<T1>{}(p.first);
auto h2 = std::hash<T2>{}(p.second);

// Mainly for demonstration purposes, i.e. works but is overly simple
// In the real world, use sth. like boost.hash_combine
return h1 ^ h2;
}
};

void function()
{
std::unordered_map<MyPair, double, pair_hash> M;
}

最佳答案

是的,您使用了我之前提供的多精度哈希并添加了 std::pair 的哈希。我不喜欢手动处理哈希组合(良好的通用哈希组合并非微不足道)。

所以我会对 boost::hash_combine 做同样的事情:

template <typename K, typename V>
struct hash<std::pair<K, V> >
{
size_t operator()(std::pair<K, V> const& pair) const {
size_t seed = std::hash<K>{}(pair.first);
boost::hash_combine(seed, pair.second);
return seed;
}
};

Live On MSVC RexTester

#include <iostream>
#include <iomanip>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_int/serialize.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>

#include <boost/functional/hash.hpp>

namespace mp_hashing {
namespace io = boost::iostreams;

struct hash_sink {
hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}

typedef char char_type;
typedef io::sink_tag category;

std::streamsize write(const char* s, std::streamsize n) {
boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
return n;
}
private:
size_t* _ptr;
};

template <typename T> struct hash_impl {
size_t operator()(T const& v) const {
using namespace boost;
size_t seed = 0;
{
iostreams::stream<hash_sink> os(seed);
archive::binary_oarchive oa(os, archive::no_header | archive::no_codecvt);
oa << v;
}
return seed;
}
};
}

#include <unordered_map>
#include <boost/unordered_map.hpp>

namespace std {
template <typename backend>
struct hash<boost::multiprecision::number<backend> >
: mp_hashing::hash_impl<boost::multiprecision::number<backend> >
{};

template <typename K, typename V>
struct hash<std::pair<K, V> >
{
size_t operator()(std::pair<K, V> const& pair) const {
size_t seed = std::hash<K>{}(pair.first);
boost::hash_combine(seed, pair.second);
return seed;
}
};
}

int main() {
using boost::multiprecision::cpp_int;

std::unordered_map<std::pair<cpp_int, int>, int> m {
{ { cpp_int(1) << 111, -1 }, 1 },
{ { cpp_int(2) << 222, -2 }, 2 },
{ { cpp_int(3) << 333, -3 }, 3 },
};

for (auto& p : m)
std::cout << p.first.first << " -> " << p.second << "\n";
}

关于C++:使用一对 (cpp_int, int) 整数作为 unordered_map 中的键(其中 cpp_int 是 boost 多精度整数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47731764/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com