Rubyで乱数とランダム文字列を生成する方法を徹底解説
Rubyで乱数やランダムな文字列を生成する方法を学びたいなら、ここがまさにうってつけの場所です。
この記事では、Rubyにおける乱数生成のさまざまなテクニックを、具体例とともにわかりやすく解説します。
乱数を使えば、配列からランダムに要素を選んだり、リストから当選者を抽選したり、サイコロの目をシミュレートしたりと、幅広い用途に活用できます。
Rubyには、性質の異なる複数の乱数生成方法が用意されています。
たとえば…
randメソッドには3通りの使い方があります。
- 引数なしで
randを呼び出すと、0から1までの浮動小数点数(例: 0.4836732493)が返される - 整数を引数に渡す(
rand(10))と、0からその数未満までの整数が返される - 範囲オブジェクトを引数に渡す(
rand(1..20))と、その範囲の始点から終点までの整数が返される
その他にも、Rubyでランダム性を得るための方法があります。
- Array#shuffleメソッド
- Array#sampleメソッド
- SecureRandomクラス
それでは、具体的な例を見ていきましょう!
乱数を生成する基本
Rubyで乱数を生成するには、randメソッドを使用します。
rand 100 > 41
引数なしで呼び出した場合、randは浮動小数点数(0.4836732493など)を返します。
引数を渡すと、0からその数未満(その数自体は含まない)までの整数が生成されます。
Rubyでの乱数生成はとても簡単ですが、「0からではなく特定の範囲内で乱数が欲しい」という場合はどうすればよいのでしょうか?
ご安心ください。範囲オブジェクトを使えば、思いどおりの範囲で乱数を取得できます。
例:
rand 200..500 > 352
セキュアな乱数の生成(SecureRandom)
randメソッドが生成する乱数は、シンプルなアプリケーションであれば十分です。
しかし、パスワードリセットトークンの生成など、セキュリティに関わる用途で使いたい場合は、Ruby標準ライブラリのSecureRandomを使用すべきです。
SecureRandomは、Unix系システムでは/dev/urandomを、WindowsではCryptAcquireContext / CryptGenRandom APIをシード源として使用します。暗号学的に安全な乱数が必要な場面では、必ずこちらを使いましょう。
以下は使用例です:
require 'securerandom' SecureRandom.random_number > 0.232
ご覧のとおり、使い方はrandとよく似ていて、最大値を指定することもできます。
例:
SecureRandom.random_number(100) > 72
SecureRandomには、他にもさまざまな出力形式が用意されています。
hexメソッドを使うと、固定長の16進数文字列を生成できます。
SecureRandom.hex > "87694e9e5231abca6de39c58cdfbe307"
さらに、Ruby 2.5からはランダムな英数字文字列を生成できる新しいメソッドが追加されました。
SecureRandom.alphanumeric > "PSNVXOeDpnFikJPC"
配列からランダムに要素を取り出す方法
次に、リストからランダムに要素を1つ選びたい場合の方法を紹介します。
まず思いつくのは、次のようなコードかもしれません。
[5, 15, 30, 60].shuffle.first > 30
しかし、Rubyにはこの目的に適した(しかも高速な)sampleメソッドが用意されています。
[5, 15, 30, 60].sample > 5
sampleは範囲オブジェクトに対しても使えます。次のコードは、ランダムなアルファベット1文字を生成します。
('a'..'z').to_a.sample
> b
sampleに整数を引数として渡すと、配列からN個の重複しない要素を取り出せます。
[1,2,3].sample(2) > [1, 2]
また、カスタムの乱数生成器を引数として渡すことも可能です。
[1,2,3].sample(random: SecureRandom)
ランダムな文字列を生成する
乱数の最も実用的な応用例のひとつが、任意の文字セットを使ったランダム文字列の生成です。コードは次のとおりです。
def generate_code(number)
charset = Array('A'..'Z') + Array('a'..'z')
Array.new(number) { charset.sample }.join
end
puts generate_code(20)
このコードでは、いくつかのテクニックが組み合わされています。
まず、範囲オブジェクトを配列に変換して文字セット(charset)を準備します。次に、ブロック付きのArray.newを利用しています。これにより、ブロックが返す値で「サイズnの配列」を初期化でき、その結果をjoinで連結して文字列にしています。
このコードを実行すると、TufwGfXZskHlPcYrLNKgのような形式の文字列が生成されます。
文字セットは、数字を追加するなど、用途に合わせて自由にカスタマイズできます。
乱数生成器へのシード設定
randなどのメソッドが生成する値を制御したい場合は、シード(seed)を設定することができます。
シードとは何でしょうか?
シードとは、乱数列の起点となる数値のことです。
生成されるすべての乱数はこのシードから導出されます。
そのため、良質な乱数列を得るためには、シードの質が重要になります。
Rubyでは通常、シードの管理は自動的に行われます(より高いセキュリティが必要な場合はSecureRandomを使用してください)。ただし、テストやデバッグなど一部のシナリオでは、自分でシードを設定したいこともあるでしょう。
その場合は、srandメソッドを使用します。
次のように使います:
Kernel.srand(1)
シードを設定すれば、ジェネレーターがどの数値を出力するかを正確に予測できます。
シードに1を指定した場合の出力例:
Array.new(5) { rand(1..10) }
# [6, 9, 10, 6, 1]
再度シードを1に設定すると、同じように6、9、10…という順序で同じ乱数列が再現されます。これはテストの再現性を確保したいときに非常に便利です。
まとめ
以上で解説は終わりです!これであなたも、Rubyプログラムの中で自由に乱数を活用できるようになりました 🙂
この記事が役に立ったと思ったら、ぜひ友人にもシェアしてください。また、ニュースレターを購読していただければ、最新の記事をお見逃しなく!
-
加重乱数(重み付き乱数)を生成する方法【Ruby実装例つき】
通常、乱数は「一様分布(uniform distribution)」に従います。これは、どの数値が選ばれる確率もすべて等しいという意味です。 しかし、特定の数値が他の数値よりも高い確率で選ばれるようにしたい場合は、別の戦略が必要になります。それが加重乱数ジェネレーター(重み付き乱数生成器)です。 実際の応用例としては、次のようなものが挙げられます。 ゲーム内のルートテーブル:敵が異なるアイテムを、それぞれ異なるドロップ率で落とす仕組み 抽選会:抽選券を多く持っている人ほど、当選する確率が高くなる仕組み シンプルな方法:配列を使う戦略 抽選会の例で考えてみると、すぐに思いつく解決策があります
-
Rubyで乱数を生成する方法まとめ:rand・srand・Randomクラスから正規分布、SecureRandomまで
乱数は、ゲーム開発、暗号化、シミュレーションの構築など、さまざまな場面で活用される重要な要素です。しかし技術的に言えば、コンピュータは純粋な計算によって真の乱数を生成することはできません。決定論的なデバイスで真にランダムな値を作り出すことは根本的に不可能であり、私たちが扱えるのは、あたかもランダムに生成されたように見える数値の連なり、すなわち「疑似乱数」だけです。 本記事では、Rubyで乱数を生成するためのさまざまな方法を紹介します。 Kernel#randで乱数を生成する まずは最も基本的なrandメソッドから始めましょう。randを引数なしで呼び出すと、0.0以上1.0未満の浮動小数点数が