こんにちは! フリーエンジニアの長瀬です。
今回はRubyのrandom、乱数を生成する方法について解説していきます!
一概に乱数と言っても乱数には色々な種類がありケースごとに使い分けていかないといけません。
この記事では、rubyでのrandomの扱い方について
【基礎】乱数の種を設定する
【基礎】ランダムな数字の生成
【発展】ランダムな文字列の生成
【発展】ランダムにarrayをシャッフル
【発展】ランダムに配列の要素を取り出す
【発展】securerandomを使って、ユニークな数値を作成する
といった応用的な内容についても解説していきます。
乱数とは
乱数とは規則性のない数字のことで、
3、70、-10、32、-9、62・・・
のようにランダムに割り当てられた数字のことをいいます。
プログラミングの分野では乱数を使用する機会が多く、すごろくのゲームや表示順をランダムに並び替えを行うとき、パスワードの自動生成などでよく使われます。
Rubyではそんな乱数を生成するためにいくつかの方法が用意されています。
次項ではさっそく使い方についてみていきましょう。
ランダム(random)の基本的な使い方
Rubyにおけるランダム(random)
Rubyでランダムな数字(乱数)を発生させるための方法は以下の2つです。
- Kernelクラスに定義されたrandメソッド
- Randomクラスに定義されたrandメソッド
主な違いはFloat(少数点を含んだ数値)を扱うことができるかです。
Kernel#randはFloatをそのまま扱うことができませんが、Random#randはFloatを受け取って、Floatの乱数を発生させることができます。
乱数の種を設定する
すべてのプログラミングにおいて乱数の種を理解することは大切です。
乱数の種とは、乱数を生成する際に元となる数値のことです。
実はプログラミング上の乱数は擬似乱数と呼ばれ、「本物の乱数」とは区別されます。
「擬似ってことは完全にランダムな数値ではないってこと?」
そうなんです。実はプログラミング上の乱数は残念ながら完璧にランダムな数値ではありません。
なので、同じ乱数の種からは同じ乱数が順番に生成されます。
ということは、本物の乱数により近づけていくためには乱数の種を毎回変えて乱数を生成するべきです。
rubyで乱数の種を設定する方法はそれぞれ
- Kernel#randのsrandメソッド
- Random#randの初期値
です。
では、それぞれサンプルコードで確認していきましょう。
[Kernel#randの場合]
srand(88) 5.times do puts rand(12) end
[実行結果]
8 0 1 10 4
[Random#randの場合]
random = Random.new(88) 5.times do puts random.rand(12) end
[実行結果]
8 0 1 10 4
このように、同じ乱数の種(88)を渡した結果は常に同じになっていることがわかります。
また、今回は乱数の種を手動で入力しましたが、乱数の種を設定する方法にはよく現在時刻が使用されます。
現在時刻であれば、完璧にランダムではありませんがある程度ランダムな乱数の種として機能するからです。
実はRubyでは、乱数の種を省略した場合自分で現在時刻を使って乱数の種を設定しなくても自動的に、現在の時刻、プロセスID、srandを呼び出した回数などを参考にランダムな乱数の種を作成してくれます。
なので、ランダムな乱数の種を作成する場合には乱数の種を省略してOKです。
ランダムな数字の生成
では実際にランダムな数値を作成してきましょう。
まずはKernel#randからです。
乱数の種は省略して書きます。
10.times do print "#{rand(10)} " #1〜9までの数値 end 10.times do print "#{rand(4.8)} " #1〜3までの数値 end
[実行結果]
2 7 1 9 3 9 8 8 0 8 2 2 0 1 3 2 0 0 2 1
このように、整数値10を与えた場合は0〜9の数字がランダムに返されます。
Kernel#randのFloatですが、4.8は4として扱われます。
というのも、Floatは少数部分は省いた後、その数の絶対値として扱われるからです。
なので例えば、rand(-3.234234)はrand(3)で、rand(-23.1234141)はrand(23)と同じです。
またrandでは範囲オブジェクトを渡すことができます。
範囲オブジェクトを使えば、Floatも扱うことができます。
10.times do print "#{rand(1..10)} " end 3.times do print "#{rand(2.0..3.0)} " end 3.times do print "#{rand(2.7..2.8)} " end
[実行結果]
10 10 1 6 10 8 6 6 2 4 2.1083541225992195 2.7853897133756753 2.847603590975523 2.70918062792426 2.7883550987451726 2.771918027115617
ここで1つ気をつけなければならないのは、範囲オブジェクトでドットが2つの演算子(..)を使用した場合は最大値を含むという点です。
(ドットが3つ…の場合最大値を含まない)
さきほどはrand(10)とすると0〜9の数値でしたが,rand(1..10)は1〜10までの数値を返します。
混同しやすい点なので、覚えておきましょう。
次はRandom#randの場合です。
random = Random.new() 10.times do print "#{random.rand(10)} " #1〜9までの数値 end 3.times do print "#{random.rand(4.8)} " #0.0〜4.8までの数値 end
[実行結果]
7 4 5 1 8 9 9 2 0 2 2.590662476913416 0.7253362059816849 1.1154553072643587
さきほどのKernel#randと比べてみてみると、一目瞭然です。
そうです、Floatをしっかりと解釈していますね。
Random#randの場合はrandom.rand(4.8)のように引数を与えるだけで0.0〜4.8までの数値を返してくれます。
同様に範囲オブジェクトも使用可能です。
random = Random.new() 10.times do print "#{random.rand(1..10)} " end 3.times do print "#{random.rand(2.0..3.0)} " end 3.times do print "#{random.rand(2.7..2.8)} " end
[実行結果]
8 2 2 1 7 4 10 10 2 9 2.2046917956365313 2.2187304527963834 2.5738729113402106 2.7983787713646606 2.7797992812680654 2.728137427385851
Kernel#randの場合と同じ結果になります。
ここでは範囲オブジェクトを使って乱数を作成しましたが、範囲オブジェクトについて理解が浅いと感じている方はこちらを参考にしてください。
ランダム(random)の応用的な使い方
ここではrandomの応用的な使い方として、
- ランダムな文字列の生成
- ランダムにarrayをシャッフル
- ランダムに配列の要素を取り出す
- ユニークな数値を作成する
などについて紹介します!
ランダムな文字列の生成
次にランダムな文字列の生成を行っていきましょう。
ランダムな文字列の生成をするためのメソッドはRubyには装備されていないので、自分で書く必要があります。
例えばAからZまでのランダムな文字列を表示させようと思うと以下のようになります。
for i in 1..10 print ('A'..'Z').to_a[rand(26)] end
[実行結果]
CDODVWVXZA
このように文字列を生成できていることがわかります!
ランダムにarrayをシャッフル
randを利用してarrayのシャッフルを行うこともできます。
array = [1,2,3,4,5] p array.sort_by{rand}
[実行結果]
[3, 5, 2, 4, 1]
このようにsort_byメソッドの引数にrandを渡すことによって、ランダムに並び替えを行うことができます。
ランダムに配列の要素を取り出す
乱数を使えば、配列の中からランダムに1つ取り出すことも簡単にできます。
array = ["red","green","yellow"] 3.times do p array[rand(3)] end
[実行結果]
"green" "red" "red"
このようにrandをindexとして指定するだけです。
securerandomを使って、ユニークな数値を作成する
securerandomというライブラリを使えば、ユニーク(重複しない)数値を簡単に作成できます。
require 'securerandom' p SecureRandom.hex(32) p SecureRandom.uuid p SecureRandom.base64(16)
[実行結果]
"bd1d8c52953d92aaada10139bf6db256881f7a13947af2516cf5e7363d5b58a8" "aa73d3d1-16ed-4bc7-81e8-765e34b1a263" "NysbLF4qFHYtM6o5LLsN7w=="
16進数、uuid(Universally Unique IDentifier)、base64など生成できる数値は豊富です。
Rubyを独学で頑張っているけど先が見えない方のために
そんな方、実はいらっしゃるのではないでしょうか?
そんな方であれば、これから先の話は必要ないでしょう。そっとページの閉じるボタンを押しましょう。
しかし、「先が見えない」と心の底では勘付いているそこの奥さん。この先を読み進めて、一緒に課題を深堀りしていきましょう。
なぜ「先が見えない」という不安や悩みを抱えてしまうのか
さて、「一寸先は闇だ・・・」とお悩みを抱えている方に、なぜ独学でRubyを勉強しているにもかかわらず、そのような現状を抱えてしまうのか、一緒に考えていきましょう。
先が見えない現状を踏まえ、課題として考えられるものは以下のどれかに該当するでしょう。
- プログラミングの上達が見えない
- プログラミングを継続できない気がする
- プログラミングスキルを習得した姿がイメージできない
- プログラミングスキルを活かした仕事を獲得するイメージができない
これらのどれかに該当することによって、「なんとなくプログラミング学習をしている」という状態になってしまいます。
これらの要因は、三日坊主になる理論と同じなんですが、「プログラミング学習をしなきゃ」とプログラミング学習を頑張ってしまっている状態になってしまっています。
受験勉強をやった経験のある方なら頭がもげるほどに首を縦に振ってしまう方も多いのですが、「今日も5時間勉強するぞ」や「今日はこの章を終わらすぞ」というように、学習を進めることに意識が行き過ぎてしまうと、ある程度学習を継続した後に「先が見えない・・・」となってしまいます。
未来に光を当て、プログラミング学習を「成果が出るもの」にするために
先ほど、「なぜ先が見えないという悩みや不安を抱えてしまうのか」という疑問に対しての答えを示していきました。
これらの課題というのは、独学をしていれば9割の方がぶつかってしまう壁だそうで、いわば、あるあるの現象なのです。
独学をしていて、「なんか前に進めていないぞ」と感じるのはこのせいなんですね。甘く見がちですが、非常にやっかい。
これがさらにやっかいさを極めているのは、上記に挙げた課題のほとんどが、1人で解決できないものばかりだからです。
実は、これらのほとんどが経験者に助けてもらいながら解決しないと、すぐに違う方向へと流れてしまいます。
そう言い切れるのは、以前の私もそうだったからです。
エンジニアやプログラマー関連のキャリアに詳しい方や現役のエンジニアに相談しながら修正を加え、学習を実践して今があります。
という方もいるでしょう。そういう時にこそ、プログラミングスクールの無料カウンセリングを利用するのです。
という考えに辿りついてしまいますよね。結論から言うと弊社では、そういった強引な営業等を行うことはありませんので、安心して受講できます。
「プログラミング学習の先ある未来」を光で明るく照らすには、弊社の無料カウンセリングがぴったりだと断言できます。それくらい無料カウンセリングに自信を持っているのです。
さらに、無料カウンセリングには以下の3大特典もついてきます!
- 「最短1ヶ月で開発ができる学習方法」電子書籍(非売品)
- 効率的なオリジナル学習カリキュラム
- 未経験の転職(フリーランス)を可能にするキャリアサポート
上記の特典だけでも他のスクールにはないポイントだと自信を持っている無料カウンセリング特典です。
ただプログラミング学習をする毎日から、ワクワクしながらプログラミング学習できる毎日に変える体験を一度でいいのでしてみませんか?
まとめ
今回はrubyで乱数を生成する方法について、
・Rubyにおけるランダム(random)
・乱数の種を設定する
・ランダムな数字の生成
・ランダムな文字列の生成
・ランダムにarrayをシャッフル
・ランダムに配列の要素を取り出す
・securerandomを使って、ユニークな数値を作成する
などについて解説していきました。
rubyはrandomで数字しか生成ができませんが、使い方によって色々な用途に使えることがわかっていただけたと思います。
乱数の生成は様々な部分で出てくるので、しっかりと確認するようにしましょう!