更新日:
【Ruby】 randメソッドの使い方を学んでランダムなデータを作成しよう
randメソッドとは、擬似乱数を生成してくれるメソッドのことです。引数には、整数やRangeオブジェクトを渡して乱数の上限や範囲を指定する事が出来ます。
randメソッドは、以下のコードのように擬似乱数を生成する事が出来ます。
1
2
irb(main):001:0> rand # 疑似乱数浮動小数点数を返す
=> 0.2575753533357512
また、以下のコードのように引数に整数やRangeオブジェクトを渡すと、生成される擬似乱数の上限や範囲を指定する事が出来ます。
1
2
3
4
irb(main):002:0> rand(5) # 0以上5未満の整数を返す
=> 2
irb(main):003:0> rand(1..5) # rangeで指定された範囲の値を返す
=> 5
randメソッドを使えばランダムなデータを簡単に作成することが出来るので、是非マスターしましょう!
randメソッドの基本的な使い方
この章では、基本構文や引数の指定方法についてサンプルコードを使用して解説するので、randメソッドで何が出来るのかイメージしながら学ぶことが出来ます。
基本構文
randメソッドは、擬似乱数を生成してくれるメソッドです。引数には、以下のコードのように整数かRangeオブジェクトを渡す事が出来ます。
1
2
3
4
# rand(max = 0), # rand(range)
rand(整数) # 上限を指定する
rand(Rangeオブジェクト) # 範囲を指定する
引数に整数を渡した場合は、0以上指定した整数未満の整数を返します。引数にRangeオブジェクトを渡した場合は、その範囲の値を返します。
例えば、以下のコードのようにrand(5)
とした場合は、0以上5未満の整数を返します。
1
2
irb(main):002:0> rand(5) # 0以上5未満の整数を返す
=> 2
そしてRangeオブジェクトを使ったrand(1..5)
の以下のコードは、指定した範囲の値を返します。1..5
は、1以上5以下の値を整数を返します。
1
2
irb(main):003:0> rand(1..5) # rangeで指定された範囲の値を返す
=> 5
randメソッドの引数の詳細は、次の章で解説します。
引数の指定方法
randメソッドの引数に指定する事が出来るのは、整数やRangeオブジェクト以外にも浮動小数点数があります。
randメソッドの引数に指定するもので、どんな擬似乱数を生成することが可能になるのかそれぞれの指定方法を学んでいきましょう。
引数を指定しない場合
randメソッドの引数を指定しない場合は、擬似乱数の浮動小数点数を返します。
1
2
irb(main):001:0> rand # 疑似乱数浮動小数点数を返す
=> 0.2575753533357512
返り値の浮動小数点数の範囲は、0.0以上1.0未満の値を返します。
整数を指定する場合
randメソッドの引数に正の整数を指定する場合は、擬似乱数の上限を決めることが出来ます。引数に指定した整数3
は上限に含まれないので注意してください。
1
2
irb(main):001:0> rand(3) # 0以上3未満の整数を返す
=> 1
しかし負の整数を指定した場合は、そのまま負の整数が渡されるのではなくその値の絶対値が渡されます。
例えば以下のコードのように、randメソッドの引数に-3
を指定したとしても絶対値3
として扱われます。
1
2
3
# rand(3)として扱われるので、0以上3未満の整数を返す
irb(main):001:0> rand(-3)
=> 2
浮動小数点を指定する場合
randメソッドの引数は、整数以外にも浮動小数点5.3
を指定して擬似乱数の上限を決めることが出来ます。
1
2
irb(main):001:0> rand(5.3)
=> 1
しかし、実際には引数に渡した5.3
の小数点以下は切り捨てられて5
となり、その値が絶対値として扱われます。つまり、rand(5.3)
はrand(5)
として扱われるので、0以上5未満の擬似乱数の生成を行います。
1
2
irb(main):001:0> rand(5.3) # rand(5)として扱われる
=> 1
Rangeオブジェクトを指定する場合
randメソッドの引数は、Rangeオブジェクトを指定して擬似乱数の範囲を決めることが出来ます。
1
2
irb(main):001:0> rand(1..5) # 1 以上 5 以下の範囲の値を返す
=> 5
引数に渡すRangeオブジェクトには、以下のコードのようにRange.new
や範囲演算子..
や...
を使用することが出来ます。
1
2
3
4
5
6
irb(main):001:0> Range.new(1, 5) # 1 以上 5 以下
=> 1..5
irb(main):002:0> 1..5 # 同上
=> 1..5
irb(main):003:0> 1...5 # 1 以上 5 未満
=> 1...5
1
2
3
4
5
6
irb(main):001:0> rand(Range.new(1, 5)) # 1以上5以下の擬似乱数を生成
=> 1
irb(main):002:0> rand(1..5) # 同上
=> 3
irb(main):003:0> rand(1...5) # 1 以上 5 未満の擬似乱数を生成
=> 4
1..5
は5
を含んだ範囲になりますが、1...5
は5
を含まない範囲になるので注意してください。そのため以下のコードでは、生成される擬似乱数の範囲が変わります。
1
2
3
rand(1..5) # 1 以上 5 以下の範囲の擬似乱数を生成する
rand(1...5) # 1 以上 5 未満の範囲の擬似乱数を生成する
そして、randメソッドの引数に範囲演算子で範囲を指定する場合は、以下のコードのように文字列にするとエラーが発生します。
1
2
3
4
5
irb(main):002:0> rand("1".."5") # 文字列だとエラーが発生する
TypeError (no implicit conversion of Range into Integer)
irb(main):003:0> rand(1..5) # 数値だと正常に処理される
=> 3
randメソッドに範囲を渡す場合は、数値で指定した範囲出なければいけないので注意してください。
randメソッドの応用的な使い方
この章では、randメソッドの使い所や擬似乱数を生成する際に推奨されているRandomクラスの使い方など少し応用的な事について解説をします。
randメソッドの使い所
randメソッドは、ランダムなデータを作成する場合に良く使われます。
例えば、以下のコードのように記述することで5文字のA~Zのアルファベットのランダムな文字列を作成することが出来ます。
1
2
irb(main):001:0> (0...5).map{ ('A'..'Z').to_a[rand(26)] }.join
=> "GXICD"
上記のコードは、randメソッド以外にもmapメソッドやjoinメソッド、範囲演算(..
や...
)が使用されているのでどんな処理をしているのか少し分かりづらいですね。順番に解説します。
1文字のランダムな値を取得する
まずは、以下の箇所の処理から解説します。ここの処理は、A~Zの中からランダムな値を1文字だけ取得しています。
('A'..'Z')
は、範囲演算子..
を使用しているので、AからZが含まれた文字列の範囲を表します。そこにto_aメソッドを実行すると、以下のコードのように「A~Zの文字列の要素を持つ配列へ変換」します。
1
2
3
irb(main):002:0> ('A'..'Z').to_a
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
"M", "N", "O", "P", "Q", "R", "S","T", "U", "V", "W", "X", "Y", "Z"]
この配列の要素は、全部で26
あります。配列の要素は0
から始まるので、最初と最後の要素を取得するには、以下のコードのように記述します。
1
2
3
4
5
6
7
irb(main):003:0> ('A'..'Z').to_a.length
=> 26
irb(main):004:0> ('A'..'Z').to_a[0]
=> "A" # 最初の要素
irb(main):005:0> ('A'..'Z').to_a[25]
=> "Z" # 最後の要素
しかし、ここではランダムな文字列を取得したいので、以下のコードのように指定する要素をrand(26)
にします。rand(26)
は、0以上26未満のランダムな値を返すので、A~Zのランダムな文字列を取得することが出来ます。
1
2
irb(main):028:0> ('A'..'Z').to_a[rand(26)]
=> "L"
したがって上記の処理は、A~Zの文字列の要素を持つ配列へ変換し、その配列の要素をランダムに取得することが分かりました。
5文字のランダムな値を取得する
次は、範囲演算子・mapメソッド・joinメソッドの箇所の解説をします。ここの処理は、A~Zの中からランダムな値を5文字取得出来るようにしています。
まずは(0...5).map{}
内に先ほどの処理を記述して実行すると、以下のコードのようにランダムな文字列の要素を持つ配列が返ります。
1
2
irb(main):001:0> (0...5).map{ ('A'..'Z').to_a[rand(26)] }
=> ["D", "H", "I", "K", "W"]
上記の(0...5)
は、0以上5未満の範囲0, 1, 2, 3, 4
を表します。mapメソッドでは、その範囲の数だけブロック内の処理が繰り返されて、新しい配列を返しています。
つまり、A~Z内のランダムな文字列を持つ配列の要素を5つ作成しているのです。
1
2
irb(main):031:0> (0...5).map{ ('A'..'Z').to_a[rand(26)] }.join
=> "DHIKW"
そして上記のコードのように、配列の要素を文字列に変換して結合するjoinメソッドを使うと、A~Zの5文字のランダムな文字列のデータを生成することが出来ます。
Randomクラスを使う
Randomクラスは、Ruby1.9.3以降で導入された擬似乱数を生成してくれるクラスです。組み込み関数のrandメソッドと比べて、高速でメモリ効率が良く、数学的にも優れたアルゴリズムが使用されています。
以下のコードのようにrandの前にRandomを記述するだけで、randメソッドと同じように使用する事が出来ます。
1
2
3
4
5
6
irb(main):001:0> Random.rand # 疑似乱数浮動小数点数を返す
=> 0.04026080994605985
irb(main):002:0> Random.rand(5) # 0以上5未満の整数を返す
=> 3
irb(main):003:0> Random.rand(1..5) # rangeで指定された範囲の値を返す
=> 3
また、randメソッドの場合は浮動小数点5.5
を指定しても、小数点が切り捨てられ絶対値として5
を渡していることになりましたが、 以下のコードのようにRandomクラスを使用すると浮動小数点を渡す事が出来ます。
1
2
3
4
irb(main):004:0> rand(5.5)
=> 4 # 5が渡されたと認識される
irb(main):005:0> Random.rand(5.5)
=> 2.2116582489574736 # 5.5が渡されたと認識される
また、以下のコードのようにfloorメソッドやceilメソッドを併用することで小数点を制御する事が出来ます。
1
2
3
4
irb(main):006:0> Random.rand(5.5).floor(3)
=> 5.297 # 小数点以下3桁を切り上げて取得する
irb(main):007:0> Random.rand(5.5).ceil(2)
=> 1.96 # 小数点以下2桁を切り捨てて取得する
このように、Randomクラスを使用することで優れたアルゴリズムで擬似乱数を生成する事が出来ます。ランダムな擬似乱数を生成する場合は、組み込み関数のrandメソッドではなくRandomクラスを使用する事が推奨されます。
この記事のまとめ
- randメソッドとは、擬似乱数を生成してくれるメソッドのこと
- ランダムなデータを作成する際に便利なメソッド
- 擬似乱数の上限や範囲を決める事が出来る!