http://d.puremagic.com/issues/show_bug.cgi?id=5849

           Summary: std.random.dice is better as a range
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nob...@puremagic.com
        ReportedBy: bearophile_h...@eml.cc


--- Comment #0 from bearophile_h...@eml.cc 2011-04-16 18:06:59 PDT ---
When I have to use std.random.dice the frequencies don't change often, but I
usually have to compute many random values efficiently. Calling dice() many
times is not efficient, because it performs some preprocessing of the given
frequencies.

So I suggest to replace the function dice(xxx) with a range that generates the
results.

So the current usage of:
dice(70, 20, 10)
gets replaced by:
dice(70, 20, 10).front

And you are able to write:

take(dice(70, 20, 10), 5)

The good thing of this generator is its performance compared to the function.
See the performance difference between the two following implementations (5.3
seconds for the first version and 0.7 seconds for the second one).

------------------------

import std.stdio, std.random, std.string;

void main() {
  enum int N = 10_000_000;
  enum pr = [1/5., 1/6., 1/7., 1/8., 1/9., 1/10., 1/11., 1759/27720.];

  double[pr.length] counts = 0.0;
  foreach (i; 0 .. N)
    counts[dice(pr)]++;

  foreach (i, p; pr)
    writefln("%.8f   %.8f", p, counts[i] / N);
}

------------------------

import std.stdio, std.random, std.string;

void main() {
  enum int N = 10_000_000;
  enum pr = [1/5., 1/6., 1/7., 1/8., 1/9., 1/10., 1/11., 1759/27720.];
  double[pr.length] cumulatives = pr[];
  foreach (i, ref c; cumulatives[1 .. $-1])
    c += cumulatives[i];
  cumulatives[$-1] = 1.0;

  double[pr.length] counts = 0.0;
  auto rnd = Xorshift(unpredictableSeed());
  foreach (i; 0 .. N) {
    double rnum = rnd.front() / cast(double)typeof(rnd.front()).max;
    rnd.popFront();
    int j;
    for ( ; rnum > cumulatives[j]; j++) {}
    counts[j]++;
  }

  foreach (i, p; pr)
    writefln("%.8f   %.8f", p, counts[i] / N);
}

-------------------------

See also some other improvements I have suggested for std.random.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------

Reply via email to