# Stateless pseudorandom/hash algorithm for ℤⁿ → [0,1)

There's a problem which I had on a number of unrelated occasions which I usually work around in some way or another. Deep inside, though, it bothers me that I haven't ever found a “proper” solution to this:

Given an n-tuple of integers, how do I derive a stateless pseudorandom number / hash value in the half-open interval [0,1)?

The usual “solution” people use in this situation is to multiply the parameters by some large primes, or bit-shift them, or do any other complex calculation which produces a result that is “random enough” for the given purpose. I guess these algorithms have been cargo-culted over a long time, maybe from a PRNG implementation.

Instead of copying one of the circulating code snippets, I'd like to really understand what's going on here. Is there an algorithm or a set of algorithms which should typically be used in this kind of situation, and if so, what's the proper way to choose the constants?

• What properties do you want the hash function to have? What do you mean by stateless? How many output bits do you need? Have you looked at universal hash families? Have you looked at cryptographic hash functions? Apr 29, 2015 at 7:29
• The function should return values which are “random enough for any practical purpose”. If they are to be visualized as gray scales in a grid (which is a somewhat plausible model for what it comes down to in many cases), there shouldn't be a pattern recognizable to the eye. (I know this isn't terribly precise but I don't know how to put this better, sorry. Humans are amazing pattern recognition machines…)
– user3426575
Apr 29, 2015 at 18:54
• By stateless, I mean that there shouldn't be a state carried from one invocation of the function to the next one; if invoked later with the same parameter tuple, the function should return the same result.
– user3426575
Apr 29, 2015 at 18:55
• I don't generally need many output bits (as compared to a cryptographic hash function). The exact number varies from situation to situation; in one case, I need a uniformly distributed value from 1 to 20, while in other cases, I need a floating-point parameter which usually requires about 8–16 bits to be “smooth enough”.
– user3426575
Apr 29, 2015 at 19:08

A simple approach is to take a representation of the input in binary, using any standard encoding for the integers and for $n$-vectors of integers, and then hash the result using your favorite hash function. The output will be a binary string. Treat it as the binary representation of a number in the range $[0,1)$ (put a decimal point before the start of it, and interpret it in base 2). That's your output.