すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Ruby

【Ruby】 randメソッドの使い方を学んでランダムなデータを作成しよう

ぴっかちゃん
ぴっかちゃん

randメソッドとは、擬似乱数を生成してくれるメソッドのことです。引数には、整数やRangeオブジェクトを渡して乱数の上限や範囲を指定する事が出来ます。

randメソッドは、以下のコードのように擬似乱数を生成する事が出来ます。

irb | randメソッドの引数を指定しない場合
1
2
irb(main):001:0> rand # 疑似乱数浮動小数点数を返す
=> 0.2575753533357512

また、以下のコードのように引数に整数やRangeオブジェクトを渡すと、生成される擬似乱数の上限や範囲を指定する事が出来ます。

irb | randメソッドに引数を指定した場合
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未満の整数を返します。

irb | randメソッドの引数に整数を渡した場合
1
2
irb(main):002:0> rand(5) # 0以上5未満の整数を返す
=> 2

そしてRangeオブジェクトを使ったrand(1..5)の以下のコードは、指定した範囲の値を返します。1..5は、1以上5以下の値を整数を返します。

irb | randメソッドの引数にRangeオブジェクトを渡した場合
1
2
irb(main):003:0> rand(1..5) # rangeで指定された範囲の値を返す
=> 5

randメソッドの引数の詳細は、次の章で解説します。

引数の指定方法

randメソッドの引数に指定する事が出来るのは、整数やRangeオブジェクト以外にも浮動小数点数があります。

randメソッドの引数に指定するもので、どんな擬似乱数を生成することが可能になるのかそれぞれの指定方法を学んでいきましょう。

引数を指定しない場合

randメソッドの引数を指定しない場合は、擬似乱数の浮動小数点数を返します。

irb | 引数を指定しない場合
1
2
irb(main):001:0> rand # 疑似乱数浮動小数点数を返す
=> 0.2575753533357512

返り値の浮動小数点数の範囲は、0.0以上1.0未満の値を返します。

整数を指定する場合

randメソッドの引数に正の整数を指定する場合は、擬似乱数の上限を決めることが出来ます。引数に指定した整数3は上限に含まれないので注意してください。

irb | 引数に正の整数を指定する場合
1
2
irb(main):001:0> rand(3) # 0以上3未満の整数を返す
=> 1

しかし負の整数を指定した場合は、そのまま負の整数が渡されるのではなくその値の絶対値が渡されます。

例えば以下のコードのように、randメソッドの引数に-3を指定したとしても絶対値3として扱われます。

irb | 引数に負の整数を指定する場合
1
2
3
# rand(3)として扱われるので、0以上3未満の整数を返す
irb(main):001:0> rand(-3) 
=> 2
ポイント
  1. 引数に整数を渡すと、擬似乱数の上限を決める事が出来る
  2. 引数に指定した整数は上限に含まれない
  3. 引数に負の整数-3を渡すと、その値の絶対値3として扱われる

浮動小数点を指定する場合

randメソッドの引数は、整数以外にも浮動小数点5.3を指定して擬似乱数の上限を決めることが出来ます。

irb | 引数に浮動小数点数を指定する場合
1
2
irb(main):001:0> rand(5.3)
=> 1

しかし、実際には引数に渡した5.3の小数点以下は切り捨てられて5となり、その値が絶対値として扱われます。つまり、rand(5.3)rand(5)として扱われるので、0以上5未満の擬似乱数の生成を行います。

irb | 引数に浮動小数点数を指定する場合
1
2
irb(main):001:0> rand(5.3) # rand(5)として扱われる
=> 1
ポイント
  1. 引数に浮動小数点を指定した場合は、小数点以下は切り捨てられる
  2. 小数点以下を切り捨てられた値が絶対値として扱われる

Rangeオブジェクトを指定する場合

randメソッドの引数は、Rangeオブジェクトを指定して擬似乱数の範囲を決めることが出来ます。

irb | 引数にRangeオブジェクトを指定する場合
1
2
irb(main):001:0> rand(1..5) # 1 以上 5 以下の範囲の値を返す
=> 5

引数に渡すRangeオブジェクトには、以下のコードのようにRange.newや範囲演算子.....を使用することが出来ます。

引数に渡せるRangeオブジェクト
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
irb | randメソッドにRangeオブジェクトを指定する場合
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..55を含んだ範囲になりますが、1...55を含まない範囲になるので注意してください。そのため以下のコードでは、生成される擬似乱数の範囲が変わります。

randメソッドの引数に渡す範囲演算子の違い-->
1
2
3
rand(1..5) # 1 以上 5 以下の範囲の擬似乱数を生成する

rand(1...5) # 1 以上 5 未満の範囲の擬似乱数を生成する

そして、randメソッドの引数に範囲演算子で範囲を指定する場合は、以下のコードのように文字列にするとエラーが発生します。

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メソッドの引数まとめ
  1. 引数に渡す値が0の場合は、0.0 以上 1.0 未満の擬似乱数が生成される
  2. 引数に渡す値が正の整数の場合は、0以上その整数未満の擬似乱数が生成される

上記以外の値が引数に渡された場合は、小数点以下は切り捨てられてその値の絶対値が渡されたものとして扱われる(Rangeオブジェクトは含まない)

randメソッドの応用的な使い方

この章では、randメソッドの使い所や擬似乱数を生成する際に推奨されているRandomクラスの使い方など少し応用的な事について解説をします。

randメソッドの使い所

randメソッドは、ランダムなデータを作成する場合に良く使われます。

例えば、以下のコードのように記述することで5文字のA~Zのアルファベットのランダムな文字列を作成することが出来ます。

irb | 5文字のランダムな文字列を作成する
1
2
irb(main):001:0> (0...5).map{ ('A'..'Z').to_a[rand(26)] }.join
=> "GXICD"

上記のコードは、randメソッド以外にもmapメソッドやjoinメソッド、範囲演算(.....)が使用されているのでどんな処理をしているのか少し分かりづらいですね。順番に解説します。

1文字のランダムな値を取得する

まずは、以下の箇所の処理から解説します。ここの処理は、A~Zの中からランダムな値を1文字だけ取得しています。

mapメソッドのブロックに渡す処理の内容

('A'..'Z')は、範囲演算子..を使用しているので、AからZが含まれた文字列の範囲を表します。そこにto_aメソッドを実行すると、以下のコードのように「A~Zの文字列の要素を持つ配列へ変換」します。

irb | 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から始まるので、最初と最後の要素を取得するには、以下のコードのように記述します。

irb | 作成した配列の最初と最後の要素を取得する
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のランダムな文字列を取得することが出来ます。

irb | 作成した配列の最初と最後の要素を取得する
1
2
irb(main):028:0> ('A'..'Z').to_a[rand(26)]
=> "L"

したがって上記の処理は、A~Zの文字列の要素を持つ配列へ変換し、その配列の要素をランダムに取得することが分かりました。

5文字のランダムな値を取得する

次は、範囲演算子・mapメソッド・joinメソッドの箇所の解説をします。ここの処理は、A~Zの中からランダムな値を5文字取得出来るようにしています。

mapとjoinの処理の内容

まずは(0...5).map{}内に先ほどの処理を記述して実行すると、以下のコードのようにランダムな文字列の要素を持つ配列が返ります。

irb | ランダムな文字列の要素を持つ配列が返る
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つ作成しているのです。

irb | joinメソッドで配列の要素を文字列に変換して結合させる
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メソッドと同じように使用する事が出来ます。

irb | Randomクラスを使う場合
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クラスを使用すると浮動小数点を渡す事が出来ます。

irb | 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メソッドを併用することで小数点を制御する事が出来ます。

irb | 小数点を制御したい場合
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メソッドとは、擬似乱数を生成してくれるメソッドのこと
  • ランダムなデータを作成する際に便利なメソッド
  • 擬似乱数の上限や範囲を決める事が出来る!