Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting a unique seed string into a random, yet deterministic, float value in Ruby

I'm having a hard time with this, conceptually.

Basically, I need to accept some arbitrary unique string, and be able to convert that to a normalized float value. What the output float value is doesn't really matter, so long as the same string input always results in the same normalized float output.

So this is a hashing algorithm right? I'm familiar with SHA1 or MD5, and this seems similar to password hashing where the result is the same for the correct password. But those methods output strings of characters, I believe. And what I'm not getting is how I would turn the result of a SHA1 or MD5 into a consistent float value.

# Goal
def string_to_float(seed_string)
  # ...
end

string_to_float('abc-123') #=> 0.15789
string_to_float('abc-123') #=> 0.15789

string_to_float('def-456') #=> 0.57654
string_to_float('def-456') #=> 0.57654

So what kind of approach in Ruby can I take that would turn an arbitrary string into a random but consistent float value?

like image 211
Alex Wayne Avatar asked Aug 18 '11 18:08

Alex Wayne


1 Answers

The key part that you want is a way of converting a SHA1 or MD5 hash output into a float that is both deterministic and 1-1. Here's a simple solution based on md5. This could be used as integers too.

require 'digest/md5'

class String
  def float_hash
    (Digest::MD5.hexdigest(self).to_i(16)).to_f
  end
end

puts "example_string".float_hash  # returns 1.3084281619666243e+38

This generates a hexadecimal hash, then converts it to an integer, then converts that to a float. Each step is deterministic.

Note: as pointed out by @emboss, this reduces collision resistance because a double is 8 bytes and the hash is 16 bytes. It shouldn't be a big deal though by the sounds of your application.

like image 91
Peter Avatar answered Oct 23 '22 04:10

Peter