There are two functions for genrating random numbers in Ruby, rand()
and SecureRandom.random_number()
. This article focuses specifically non-negegative integer.
Both functions accept either a non-negative integer or an integer range as argements.
When providing an argument n
($n \ge 0, n \in \mathbb{Z}$), what values do these functions return?
Let’s begin with a test using small integers and ranges, such as 3 and 1 to 3, for easy observation.
require 'securerandom'
for i in 1..20 do
puts "#{i}: #{rand(3)}, #{SecureRandom.random_number(3)}"
end
The output shows that all generated numbers are in the range [0, 1, 2], inclusive of 0 but not including 3.
1: 1, 0
2: 1, 0
3: 0, 1
4: 0, 2
5: 0, 2
6: 1, 2
7: 0, 0
8: 2, 2
9: 1, 0
10: 0, 0
11: 2, 1
12: 1, 2
13: 2, 2
14: 1, 1
15: 2, 2
16: 1, 0
17: 2, 0
18: 2, 1
19: 2, 2
20: 0, 0
require 'securerandom'
for i in 1..20 do
puts "#{i}: #{rand(1..3)}, #{SecureRandom.random_number(1..3)}"
end
Here, all numbers generated fall within the range [1, 2, 3], inclusive of both the start number 1 and end number 3.
1: 1, 1
2: 2, 2
3: 3, 1
4: 2, 2
5: 1, 3
6: 3, 3
7: 1, 1
8: 2, 1
9: 2, 3
10: 3, 1
11: 1, 2
12: 2, 3
13: 3, 2
14: 2, 3
15: 1, 2
16: 1, 1
17: 2, 3
18: 3, 2
19: 1, 1
20: 1, 2
Can we conclude the following?
Assume the argument is $n$ ($n \ge 0, n \in \mathbb{Z}$) and the return value is $r$ ($r \in \mathbb{Z}$), then $0 \le r \lt n$.
$0 \le r \lt n \Leftrightarrow 0 \le r \le n$
$\therefore 0 \le rand(n) \le n-1$
The range starts from 0 and ends at $n-1$.
Additionally,
Assume the argument is $m..n$ ($0 \le m \le n, m \in \mathbb{Z}, n \in \mathbb{Z}$) and the return value is $r$ ($r \in \mathbb{Z}$), then $m \le r \le n$.
$\therefore m \le rand(m..n) \le n$
The range starts from $m$ and ends at $n$.
The above conclusions align with the official Ruby documentation, which states:
rand(max) → number
When
max
is an Integer,rand
returns a random integer greater than or equal to zero and less thanmax
.
rand(range) → number
When
range
is a Range,rand
returns a random number whererange.member?(number) == true
.
prng = Random.new
prng.rand(5..9) # => one of [5, 6, 7, 8, 9]
prng.rand(5...9) # => one of [5, 6, 7, 8]
According to the documentation, the observations from our tests are accurate.
This discussion excludes topics such as negative numbers and floating-point numbers.