0

I need to generate a hash from two float vectors, extracted from an orientation matrix. For this purpose I used the following code:

QByteArray hashNumber(6*sizeof(float), Qt::Uninitialized);
QVector3D vect1 = getVectorN();
QVector3D vect2 = getVectorO();

float* floatNumbers = (float*)hashNumber.data();
floatNumbers[0] = vect1.x();
floatNumbers[1] = vect1.y();
floatNumbers[2] = vect1.z();
floatNumbers[3] = vect2.x();
floatNumbers[4] = vect2.y();
floatNumbers[5] = vect2.z();

The problem is that floating point arithmetic has precision problems so most of the time when I make some direct and inverse operation on vectors, hash number is changing.

For instance, let's say that vect1 vector has value (0, 0, 5.4878049) and corresponds to some object position. When I move it back and forth, vect1 value changes in last digits (0, 0, 5.4878048), hence the hash value is not equal to previous. I know that direct float values comparison is not correct, so the question is:

What is the best way to make hash form two float vectors?

AndyG
  • 39,700
  • 8
  • 109
  • 143
Oleksandr V
  • 25
  • 1
  • 6
  • How would you use that hash value? After all, hashes are typically used *for* equality comparison and as you know, comparing equality of floats is usually not correct. – eerorika Dec 03 '15 at 16:11
  • I use it for equality comparison, however as you noticed, due to the not correct floats comparison it provides not stable result. That's why I asked, is there any common way to overcome this problem? – Oleksandr V Dec 03 '15 at 16:14
  • 1
    My point is that this problem usually doesn't exist because hashing floats has no use case. The solution is to not compare floats for equality. And since you don't compare floats for equality, you don't need to hash them. I'm guessing that you're dealing with [XY-problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – eerorika Dec 03 '15 at 16:15
  • Could you elaborate a little bit more in this part: "When I move it back and forth"? – rendon Dec 03 '15 at 16:24
  • My object is plane that can be translated in space. Let's say vect2 is a translation vector that specifies plane position. Each vect2 components is limited to [0, 1] range. When I move my plane in space (without changing orientation) only vect2 vector is changed. I can move it on some delta and then move back on the same delta. – Oleksandr V Dec 03 '15 at 16:33
  • If you know (or can estimate) your floating point calculations' margin of error, you could could round off the floating point values before computing the hash; that way "minor" differences would not effect the hash. It would still be kind of an ugly solution, though. – Jeremy Friesner Dec 03 '15 at 16:49

1 Answers1

0

Generating a hash value from a vector of floats is simple. std::hash is specialized for float. Use that for each element and combine them with a hash combination function. There is no such function in the standard library, but boost does and it doesn't depend on anything else in boost, so you can trivially copy it if you don't want to use rest of boost. There's a copy of it in this answer.

The problem is that floating point arithmetic has precision problems so most of the time when I make some direct and inverse operation on vectors, hash number is changing.

If the original value changes, even minimally, then the hash-value is completely different. That's a desireable property of a hash-function. If that's a problem for you then you shoudn't be using hashing.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326