tags:

views:

102

answers:

4

I'm searching for a hash function that takes as input any integer (positive or negative, though it could be constrained to the int range if this makes it easier), and returns a real number between -1 and 1. Is there such a function, or any obvious way to build it from another hash function?

The function doesn't have to be secure, as long as its sufficiently "random". Bonus points if a C/C++ implementation exists.

+3  A: 

What do you mean by sufficiently "random"?
You can always divide you integer by max int value and get a value between -1 and 1.

EDIT:

before normalization you can do something like

num = num^397;

and then divide by int max.

Itay
By random I mean that the output of the function should look like a sequence of random numbers, or that similar input should not generate similar output, or any other reasonable definition of randomness.
Benno
You can raise you number to some prime number power and then normalize it according to the above, it will be more "random".
Itay
+5  A: 
  1. Pick any hash-function for integers, such as boost::hash,
  2. normalize the result to 2 by dividing by half of the maximum value of an integer
  3. Subtract 1.

Here is a quick hack to demonstrate:

#include<stdio.h>

double inthash(unsigned int key)
{
  key += (key << 12);
  key ^= (key >> 22);
  key += (key << 4);
  key ^= (key >> 9);
  key += (key << 10);
  key ^= (key >> 2);
  key += (key << 7);
  key ^= (key >> 12);
  return key / 2147483647.5 - 1;
}

void main()
{
  printf("%f\n", inthash(1));
  printf("%f\n", inthash(2));
  printf("%f\n", inthash(3));
  printf("%f\n", inthash(10000));
  printf("%f\n", inthash(10001));
}

Output:

0.368240
-0.263032
-0.892034
-0.428394
-0.150713
aioobe
A: 

Nothing simpler than that. Works for any non-negative number. With a few minor modifications, also negative integer numbers can be supported.

double hash(int val)
{
    return val / ((double)INT_MAX / 2.0) - 1.0;
}

EDIT: This should work for all numbers (positive and negative):

double hash(int val)
{
    return val / (double)INT_MAX;
}

Yes, it is as trivial as it looks (It will be more exact if you use -INT_MIN for negative numbers).

codymanix
I think this has the same fault as Itay's answer, i.e. the structure of the input is completely preserved (similar input gives similar output), so its not "random" enough.
Benno
A: 

Code snippet double hash(int val) { return val / (double)INT_MAX; } have bug, because INT_MIN is -2147483648 and INT_MAX is 2147483647, so INT_MIN / INT_MAX < -1.

Manvel Avetisian