結局、以下のようにすることにしました。
c++
1#include <boost/functional/hash.hpp>
2#include <functional>
3#include <iostream>
4#include <unordered_map>
5
6
7bool eq(double lhs, double rhs) {
8 constexpr double threshold = 1e-5;
9 return std::abs(lhs - rhs)
10 <= threshold * std::max(1., std::max(std::abs(lhs), std::abs(rhs)));
11}
12
13
14struct Vector {
15 double x;
16 double y;
17 double z;
18
19 Vector(double _x, double _y, double _z) : x(_x), y(_y), z(_z) {}
20
21 bool operator==(const Vector& rhs) const {
22 return eq(x, rhs.x) && eq(y, rhs.y) && eq(z, rhs.z);
23 }
24 bool operator!=(const Vector& rhs) const { return !(*this == rhs); }
25};
26
27
28double round(double value) {
29 constexpr double threshold = 1e-5;
30 double tmp;
31 tmp = value / threshold;
32 tmp = (double)(int)(tmp + 0.5);
33 return tmp * threshold;
34}
35
36
37namespace std {
38template <>
39class hash<Vector> {
40 public:
41 size_t operator()(const Vector& vec) const {
42 size_t seed = 0;
43 boost::hash_combine(seed, std::hash<double>()(round(vec.x)));
44 boost::hash_combine(seed, std::hash<double>()(round(vec.y)));
45 boost::hash_combine(seed, std::hash<double>()(round(vec.z)));
46 return seed;
47 }
48};
49} // namespace std
50
51
52int main() {
53 Vector vec1{1., 2., 3.};
54 Vector vec2{1.000001, 2.000001, 3.000001};
55 Vector vec3{1.0001, 2.0001, 3.0001};
56
57 assert(vec1 == vec2);
58 assert(vec1 != vec3);
59
60 std::unordered_map<Vector, int> umap;
61
62 umap[vec1] = 5;
63
64 assert(umap.count(vec1));
65 assert(umap[vec1] == 5);
66
67 assert(umap.count(vec2));
68 assert(umap[vec2] == 5);
69
70 assert(!umap.count(vec3));
71}
72
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。