Reputation: 5895
Additionally, how can I format it as a string padded with zeros?
Upvotes: 76
Views: 68790
Reputation: 188
I did something like this
x = 10 #Number of digit
(rand(10 ** x) + 10**x).to_s[0..x-1]
Upvotes: 0
Reputation: 354
I ended up with using Ruby kernel srand
srand.to_s.last(10)
Docs here: Kernel#srand
Upvotes: 6
Reputation: 10063
To generate a random, 10-digit string:
# This generates a 10-digit string, where the
# minimum possible value is "0000000000", and the
# maximum possible value is "9999999999"
SecureRandom.random_number(10**10).to_s.rjust(10, '0')
Here's more detail of what's happening, shown by breaking the single line into multiple lines with explaining variables:
# Calculate the upper bound for the random number generator
# upper_bound = 10,000,000,000
upper_bound = 10**10
# n will be an integer with a minimum possible value of 0,
# and a maximum possible value of 9,999,999,999
n = SecureRandom.random_number(upper_bound)
# Convert the integer n to a string
# unpadded_str will be "0" if n == 0
# unpadded_str will be "9999999999" if n == 9_999_999_999
unpadded_str = n.to_s
# Pad the string with leading zeroes if it is less than
# 10 digits long.
# "0" would be padded to "0000000000"
# "123" would be padded to "0000000123"
# "9999999999" would not be padded, and remains unchanged as "9999999999"
padded_str = unpadded_str.rjust(10, '0')
Upvotes: 5
Reputation: 7032
('%010d' % rand(0..9999999999)).to_s
or
"#{'%010d' % rand(0..9999999999)}"
Upvotes: 4
Reputation: 1653
In my case number must be unique in my models, so I added checking block.
module StringUtil
refine String.singleton_class do
def generate_random_digits(size:)
proc = lambda{ rand.to_s[2...(2 + size)] }
if block_given?
loop do
generated = proc.call
break generated if yield(generated) # check generated num meets condition
end
else
proc.call
end
end
end
end
using StringUtil
String.generate_random_digits(3) => "763"
String.generate_random_digits(3) do |num|
User.find_by(code: num).nil?
end => "689"(This is unique in Users code)
Upvotes: 0
Reputation: 5565
Just use straightforward below.
rand(10 ** 9...10 ** 10)
Just test it on IRB with below.
(1..1000).each { puts rand(10 ** 9...10 ** 10) }
Upvotes: 2
Reputation: 898
A better approach is use Array.new()
instead of .times.map
. Rubocop recommends it.
Example:
string_size = 9
Array.new(string_size) do
rand(10).to_s
end
Rubucop, TimesMap:
https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Performance/TimesMap
Upvotes: 0
Reputation: 28285
An alternative answer, using the regexp-examples
ruby gem:
require 'regexp-examples'
/\d{10}/.random_example # => "0826423747"
There's no need to "pad with zeros" with this approach, since you are immediately generating a String
.
Upvotes: 1
Reputation: 1051
Use Kernel#rand method:
rand(1_000_000_000..9_999_999_999) # => random 10-digits number
Use times
+ map
+ join
combination:
10.times.map { rand(0..9) }.join # => random 10-digit string (may start with 0!)
Use String#% method:
"%010d" % 123348 # => "0000123348"
Use KeePass password generator library, it supports different patterns for generating random password:
KeePass::Password.generate("d{10}") # => random 10-digit string (may start with 0!)
A documentation for KeePass patterns can be found here.
Upvotes: 12
Reputation: 1424
Simplest way to generate n digit random number -
Random.new.rand((10**(n - 1))..(10**n))
generate 10 digit number number -
Random.new.rand((10**(10 - 1))..(10**10))
Upvotes: 3
Reputation: 80065
This is a fast way to generate a 10-sized string of digits:
10.times.map{rand(10)}.join # => "3401487670"
Upvotes: 41
Reputation: 4755
The most straightforward answer would probably be
rand(1e9...1e10).to_i
The to_i
part is needed because 1e9
and 1e10
are actually floats:
irb(main)> 1e9.class
=> Float
Upvotes: 18
Reputation: 304117
This technique works for any "alphabet"
(1..10).map{"0123456789".chars.to_a.sample}.join
=> "6383411680"
Upvotes: 2
Reputation: 61
Try using the SecureRandom ruby library.
It generates random numbers but the length is not specific.
Go through this link for more information: http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html
Upvotes: 3
Reputation: 14744
rand.to_s[2..11].to_i
Why? Because here's what you can get:
rand.to_s[2..9] #=> "04890612"
and then:
"04890612".to_i #=> 4890612
Note that:
4890612.to_s.length #=> 7
Which is not what you've expected!
To check that error in your own code, instead of .to_i
you may wrap it like this:
Integer(rand.to_s[2..9])
and very soon it will turn out that:
ArgumentError: invalid value for Integer(): "02939053"
So it's always better to stick to .center
, but keep in mind that:
rand(9)
sometimes may give you 0
.
To prevent that:
rand(1..9)
which will always return something withing 1..9
range.
I'm glad that I had good tests and I hope you will avoid breaking your system.
Upvotes: 12
Reputation: 96
I just want to modify first answer. rand (10**10)
may generate 9 digit random no if 0 is in first place. For ensuring 10 exact digit just modify
code = rand(10**10)
while code.to_s.length != 10
code = rand(11**11)
end
Upvotes: 3
Reputation: 3376
rand(9999999999).to_s.center(10, rand(9).to_s).to_i
is faster than
rand.to_s[2..11].to_i
You can use:
puts Benchmark.measure{(1..1000000).map{rand(9999999999).to_s.center(10, rand(9).to_s).to_i}}
and
puts Benchmark.measure{(1..1000000).map{rand.to_s[2..11].to_i}}
in Rails console to confirm that.
Upvotes: 1
Reputation: 1063
Just because it wasn't mentioned, the Kernel#sprintf
method (or it's alias Kernel#format
in the Powerpack Library) is generally preferred over the String#%
method, as mentioned in the Ruby Community Style Guide.
Of course this is highly debatable, but to provide insight:
The syntax of @quackingduck's answer would be
# considered bad
'%010d' % rand(10**10)
# considered good
sprintf('%010d', rand(10**10))
The nature of this preference is primarily due to the cryptic nature of %
. It's not very semantic by itself and without any additional context it can be confused with the %
modulo operator.
Examples from the Style Guide:
# bad
'%d %d' % [20, 10]
# => '20 10'
# good
sprintf('%d %d', 20, 10)
# => '20 10'
# good
sprintf('%{first} %{second}', first: 20, second: 10)
# => '20 10'
format('%d %d', 20, 10)
# => '20 10'
# good
format('%{first} %{second}', first: 20, second: 10)
# => '20 10'
To make justice for String#%
, I personally really like using operator-like syntaxes instead of commands, the same way you would do your_array << 'foo'
over your_array.push('123')
.
This just illustrates a tendency in the community, what's "best" is up to you.
More info in this blogpost.
Upvotes: 7
Reputation: 3732
I would like to contribute probably a simplest solution I know, which is a quite a good trick.
rand.to_s[2..11]
=> "5950281724"
Upvotes: 68
Reputation: 22296
This will work even on ruby 1.8.7:
rand(9999999999).to_s.center(10, rand(9).to_s).to_i
Upvotes: 0
Reputation: 4409
Here is an expression that will use one fewer method call than quackingduck's example.
'%011d' % rand(1e10)
One caveat, 1e10
is a Float
, and Kernel#rand
ends up calling to_i
on it, so for some higher values you might have some inconsistencies. To be more precise with a literal, you could also do:
'%011d' % rand(10_000_000_000) # Note that underscores are ignored in integer literals
Upvotes: 4
Reputation: 5895
To generate the number call rand with the result of the expression "10 to the power of 10"
rand(10 ** 10)
To pad the number with zeros you can use the string format operator
'%010d' % rand(10 ** 10)
or the rjust
method of string
rand(10 ** 10).to_s.rjust(10,'0')
Upvotes: 97