Converting a unique seed string into a random, yet deterministic, float value in Ruby
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.
Use a string as seed generator for random number generation in ruby on rails
What about
srand "a3989f5a-1c4b-11e3-8573-0025906a9230".tr('-', '').to_i(16)
It will seed Ruby rng from UUID as hex number after we strip dashes
Is any data lost when converting a Ruby float in scientific notation to an integer?
On the contrary, (deterministic but meaningless) data is added (as you demonstrated in your code sample). You're not losing any information. But it's not the same value.
Your float
has a precision of about 17 decimal digits, your int
suddenly has a precision of 51 digits. This has to do with Floating Point Arithmetic: Issues and Limitations. That "precision" arises as the result of the binary representation of a decimal floating point value, which leads to the "invention" of a series of digits in your integer.
Consider the following (in Python, which follows the same rules, as will probably all programming languages that feature arbitrarily long integers):
>>> a = int(1.5815450433041317e+51)
>>> a
1581545043304131697954259018410479150921451567054848
>>> b = a + 10000000000000000
>>> a == b
False
>>> float(a) == float(b)
True
>>> a == 1.5815450433041317e+51
True
In Python, the decimal
module would be quite a good compromise:
>>> from decimal import Decimal, getcontext
>>> a = str(29873409852730498572309485723**3) # just an arbitrary number
>>> getcontext().prec = 100
>>> cube = Decimal(a)
>>> cube ** Decimal("0.333333333333333333333333333333333333333333333333333333333
33333333333333333333")
Decimal('29873409852730498572309485722.99999999999999999999999999999999999999999
999998041297117811390088120595')
(which still has a slight rounding error due to the problem of representing 1/3
as a decimal float, but the result is obvious, isn't it?)
How to get a random number in Ruby
Use rand(range)
From Ruby Random Numbers:
If you needed a random integer to simulate a roll of a six-sided die, you'd use:
1 + rand(6)
. A roll in craps could be simulated with2 + rand(6) + rand(6)
.Finally, if you just need a random float, just call
rand
with no arguments.
As Marc-André Lafortune mentions in his answer below (go upvote it), Ruby 1.9.2 has its own Random
class (that Marc-André himself helped to debug, hence the 1.9.2 target for that feature).
For instance, in this game where you need to guess 10 numbers, you can initialize them with:
10.times.map{ 20 + Random.rand(11) }
#=> [26, 26, 22, 20, 30, 26, 23, 23, 25, 22]
Note:
Using
Random.new.rand(20..30)
(usingRandom.new
) generally would not be a good idea, as explained in detail (again) by Marc-André Lafortune, in his answer (again).But if you don't use
Random.new
, then the class methodrand
only takes amax
value, not aRange
, as banister (energetically) points out in the comment (and as documented in the docs forRandom
). Only the instance method can take aRange
, as illustrated by generate a random number with 7 digits.
This is why the equivalent of Random.new.rand(20..30)
would be 20 + Random.rand(11)
, since Random.rand(int)
returns “a random integer greater than or equal to zero and less than the argument.” 20..30
includes 30, I need to come up with a random number between 0 and 11, excluding 11.
Float value returns with double quotes from [String: AnyObject] in swift
Replace AnyObject with Any like below:
let appliedLoyalty: Float = 1.05
let appliedWallet: Float = 0.55
let custID = "puma"
let payLoad: [String: Any] = ["custid": custID, "discounts": ["loyalty": appliedLoyalty,"wallet": appliedWallet]] // custid is string value
print(payLoad)
Swift: converting String to Float and back to String again after doing some mathematical operations
Actually floats can not represent numbers accurately, you'll have to use Double.
Here is a very nice answer on that issue:
https://stackoverflow.com/a/3730040/4662531
EDIT:
Sorry, but actually Double should not be use to perform calculations (I'm assuming from the naming of your variables you are working on some banking things). That part of the above linked answer is really giving a great suggestion:
A solution that works in just about any language is to use integers
instead, and count cents. For instance, 1025 would be $10.25. Several
languages also have built-in types to deal with money. Among others,
Java has the BigDecimal class, and C# has the decimal type.
A colleague of mine that used to work in a banking company also confirmed that all calculations were done without using Floats or Double, but with Int as suggested in the link.
Why this repeats the same random number?
By calling the rand.Seed()
function, passing it a (random) seed (typically the current unix timestamp). Quoting from math/rand
package doc:
Top-level functions, such as Float64 and Int, use a default shared Source that produces a deterministic sequence of values each time a program is run. Use the Seed function to initialize the default Source if different behavior is required for each run.
Example:
rand.Seed(time.Now().UnixNano())
If rand.Seed()
is not called, the generator behaves as if seeded by 1:
Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1).
Related Topics
How to Transpose Different Sized Ruby Arrays
How to Stop Rails' Built-In Server from Listening on 0.0.0.0 by Default
Cannot Assign Requested Address - Bind(2) (Errno::Eaddrnotavail)
Mismatched Bundler Version - Bundler 2, Ruby 2.6
Which Equality Test Does Ruby's Hash Use When Comparing Keys
Add a CSS Class to <%= F.Submit %>
Rails 3.1 - Changing Default Scaffold Views and Template
Best Way to Handle Dynamic CSS in a Rails App
Possible to Use Stylesheet.Css.Erb in Rails
Integrating @Font-Face Files into Rails Asset Pipeline
Why Does a Rails App on Heroku Serve Assets via All.CSS and Locally via Individual Files
Rails Shows "Warning: Can't Verify Csrf Token Authenticity" from a Restkit Post
Undefined Local Variable Based on Syntax in Ruby