LoginSignup
3
3

More than 5 years have passed since last update.

Random.rand(-1..1) は Random.rand(3) - 1 よりずっと遅い

Last updated at Posted at 2016-08-03

動機

Ruby で 0 から 9 までの整数の乱数を発生させるのは

Random.rand(10)

でいいですよね。
(ええと,Kernel.#rand を使って rand(10) とすることもできますが,その話はまたあとで)

では,範囲が「0 から N-1 まで」ではない場合,どう書くのがいいでしょうか。

たとえば -1, 0, 1 のどれかをランダムに発生させるのに

Random.rand(3) - 1

と書けますが,このコードを見て -1, 0, 1 だと分かるまで一瞬考えちゃいますし,なんだかスマートではありません。

リファレンスマニュアルで Random.rand を見れば,

Random.rand(-1..1)

と書けることが分かります。こっちのほうが Ruby らしいですし,分かりやすいように思います。

と・こ・ろ・が!

後者は遅いんですよぉ。(今日まで知らなかったケド)

計測

ベンチマークテストをやってみましょう。

ついでに,Random.randKernel.#rand の比較もやってみます。

require 'benchmark'

iter = 10_000_000

Benchmark.bmbm do |rep|
  rep.report "Random.rand(3) - 1" do
    iter.times do
      v = Random.rand(3) - 1
    end
  end

  rep.report "Random.rand(-1..1)" do
    iter.times do
      v = Random.rand(-1..1)
    end
  end

  rep.report "rand(3) - 1" do
    iter.times do
      v = rand(3) - 1
    end
  end

  rep.report "rand(-1..1)" do
    iter.times do
      v = rand(-1..1)
    end
  end
end

結果はこんな感じ:

                         user     system      total        real
Random.rand(3) - 1   1.280000   0.000000   1.280000 (  1.295193)
Random.rand(-1..1)   3.200000   0.020000   3.220000 (  3.235467)
rand(3) - 1          2.190000   0.010000   2.200000 (  2.207524)
rand(-1..1)          2.440000   0.010000   2.450000 (  2.465236)

環境は

ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]

です。

なんで?

Random.rand の場合,Range を渡すとメチャメチャ遅い。

Kernel.#rand だと,それほどの差は無く,Random.rand の二つの結果のちょうど間に収まっています。ここがちょっと意外でした。

Random.randkernel.#rand って,中身は同じだと勝手に思い込んでましたが,違うのね。

引数に Range を渡す方式だと遅くなるのは,たぶんこういうことでしょう。
Range が渡されると,その始端と終端をまず求め,その差分を取ります。この値を上限値とする乱数をまず発生させます。その値に始端の値を足します。
始端と終端から差分をとる処理が,メソッド呼び出しのたびに毎回発生するのが無駄になっているワケですね。

大量の乱数を発生させるときは要注意です。

3
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3