# Random - based on :rand (not :random)

**URL:** <https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518>\
**Category:** Announcing\
**Tags:** library\
**Created:** [September 1, 2016, 12:16am UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518 "2016-09-01T00:16:55Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hal9000](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hal9000/32/1915_2.png) [@Hal9000](https://forum.elixirforum.com/u/Hal9000)\
**Post date:** [September 1, 2016, 12:16am UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/1 "2016-09-01T00:16:55Z")

</div>

Here is my first stab at this. README pasted below.

[https://github.com/Hal9000/elixir\_random](https://github.com/Hal9000/elixir_random)

Comments and critiques are welcome.

Thanks,  
Hal

* * *

The `Random` module is based on Erlang’s `rand` module. (See [rand — OTP 29.0.2 (stdlib 8.0.1)](http://erlang.org/doc/man/rand.html) ).  
This in turn is a newer replacement for Erlang’s deprecated `random`.

All functionality of `rand` is preserved here. The primary differences are:

- The preferred function name is `rand` (although `uniform` and `normal` will still work, for people accustomed to those).
- `rand` takes a parameter `:normal` for normal-distribution results.
- The `_s` functions are unnecessary, as state is passed (as needed) by means of an optional parameter.
- Any function that accepts a state also returns the new state (second item in tuple); other functions simply return a number.
- A distinction is made between `seed` and `seed3` (the latter of which takes a tuple of three integers rather than a state).
- The functions `export_seed` and `export_seed_s` are not really needed any longer.
- The `rand` function can take a range, e.g. `rand(50..60)`.
- The `Random` module adds `sample` (which takes a second parameter, a number defaulting to 0); this calls `Enum.take_random` which works on any enumerable.
- The `Random` module adds `shuffle` (which simply calls `Enum.shuffle` and thus can take any enumerable.
- The PRNG is seeded on module load (default algorithm is `:exsplus` just as with `:rand`); you may of course reseed at any time.

## Examples

```elixir
x = Random.rand # Random number between 0.0 and 1.0

x = Random.rand(:normal) # Random number in normally-distributed range, -1..1 is one sigma

n = Random.rand(5) # Random integer between 1 and 5

n = Random.rand(10..20) # Random integer between 10 and 20

state = Random.seed(:exsplus) # Use the explus algorithm (default), Xorshift116+, 58 bits, period = 2^116-1

state = Random.seed(:exs64) # Use the exs64 algorithm, Xorshift64, 64 bits, period = 2^64-1

state = Random.seed(:exs1024) # Use the exs1024 algorithm, Xorshift1024, 64 bits, period = 2^1024-1

state = Random.seed3(:exsplus, {1, 2, 3}) # Seed using the three integers 1, 2, 3

state = Random.seed(:exsplus, state) # Seed using the specified state

x = Random.uniform # Same as Random.rand

x = Random.normal # Same as Random.rand(:normal)

{x, state} = Random.rand(state) # Specify state and return number and a new state

{x, state} = Random.rand(:normal, state) # Specify state and return number (normal distribution) and new state

item = Random.sample(enum) # Grab one random item from any enumerable (such as a list)

list = Random.sample(enum, 3) # Grab 3 random items from any enumerable (such as a list)

list = Random.shuffle(enum) # Randomize (shuffle) an enumerable (such as a list)

```

## Notes

The `sample` and `shuffle` functions do not have state-sensitive variants.

---

<div class="post-metadata">

**Author:** ![OvermindDL1](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/32/2677_2.png) [@OvermindDL1](https://forum.elixirforum.com/u/OvermindDL1)\
**Post date:** [September 1, 2016, 1:58pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/2 "2016-09-01T13:58:36Z")

</div>

Looks good. Unsure when I would get a chance to try it sadly, but good interface. 🙂

---

<div class="post-metadata">

**Author:** ![josevalim](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/32/1787_2.png) [@josevalim](https://forum.elixirforum.com/u/josevalim)\
**Post date:** [September 1, 2016, 5:56pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/3 "2016-09-01T17:56:31Z")

</div>

I really like this too! I would love to hijack the `rand` function and make it part of Elixir’s Kernel. Would you be interested in sending a proposal or a PR to elixir for the rand/0 and rand/1 functions? It sounds like a perfect gateway to link developers to Erlang’s `:rand`. 🙂

The only change I would possibly do is to drop support for `rand(integer)` since `rand(0..5)` is much more explicit than `rand(5)`.

---

<div class="post-metadata">

**Author:** ![Hal9000](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hal9000/32/1915_2.png) [@Hal9000](https://forum.elixirforum.com/u/Hal9000)\
**Post date:** [September 1, 2016, 7:02pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/4 "2016-09-01T19:02:41Z")

</div>

I’m happy to assist any way I can. 🙂

1. Not sure of process for proposal
2. Do we want some version of seed also, if this is going into Kernel?
3. I’m ok with dropping rand(n) – only kept for compatibility.

Hal

---

<div class="post-metadata">

**Author:** ![josevalim](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/32/1787_2.png) [@josevalim](https://forum.elixirforum.com/u/josevalim)\
**Post date:** [September 1, 2016, 7:46pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/5 "2016-09-01T19:46:46Z")

</div>

If you want to send a proposal, the planned API for `rand`, similar to what you have sent here, is enough. However, given the proposal is _pretty much here_ already, it is ok to bypass that and send a PR if you prefer.

We don’t plan to have any seed or stateful function. The goal is to use `rand/0` and `rand/1` as a gateway to the actual `:rand` module. So we can explicitly document that you can get control over the seed by using the `:rand` module.

---

<div class="post-metadata">

**Author:** ![Hal9000](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hal9000/32/1915_2.png) [@Hal9000](https://forum.elixirforum.com/u/Hal9000)\
**Post date:** [September 1, 2016, 8:33pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/6 "2016-09-01T20:33:15Z")

</div>

I don’t mind sending a proposal.

I just don’t know to whom I should send it.

Hal

---

<div class="post-metadata">

**Author:** ![OvermindDL1](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/32/2677_2.png) [@OvermindDL1](https://forum.elixirforum.com/u/OvermindDL1)\
**Post date:** [September 1, 2016, 8:35pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/7 "2016-09-01T20:35:52Z")

</div>

It would be to the central Elixir github I would imagine (correct me otherwise?): [GitHub - elixir-lang/elixir: Elixir is a dynamic, functional language for building scalable and maintainable applications · GitHub](https://github.com/elixir-lang/elixir/)🙂

If you can get a PR (Pull Request) started with the basic code as jose wants, then conversation can happen within that PR to refine it so you can add the refinements until it gets merged into core. 🙂

---

<div class="post-metadata">

**Author:** ![Hal9000](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hal9000/32/1915_2.png) [@Hal9000](https://forum.elixirforum.com/u/Hal9000)\
**Post date:** [September 1, 2016, 9:29pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/8 "2016-09-01T21:29:32Z")

</div>

I don’t know the source. It’s not obvious to me where this would go.

If anyone wants to assist, let me know. Or if I can simply submit  
code/docs to someone, that is fine, too.

rand/0 and rand/1 are very few lines of code.

Hal

---

<div class="post-metadata">

**Author:** ![josevalim](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/32/1787_2.png) [@josevalim](https://forum.elixirforum.com/u/josevalim)\
**Post date:** [September 2, 2016, 6:34pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/9 "2016-09-02T18:34:02Z")

</div>

You can clone [the Elixir repo](https://github.com/elixir-lang/elixir) and then run:

```
make compile

```

Then you can add the code implementation around here:

[https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/kernel.ex#L1537](https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/kernel.ex#L1537)

And the tests around here:

[https://github.com/elixir-lang/elixir/blob/master/lib/elixir/test/elixir/kernel\_test.exs#L87](https://github.com/elixir-lang/elixir/blob/master/lib/elixir/test/elixir/kernel_test.exs#L87)

After writing code or tests, you can run the line below inside the Elixir repo to run one particular test:

```
elixirc lib/elixir/lib/kernel.ex -o lib/elixir/ebin && elixir lib/elixir/test/elixir/kernel_test.exs

```

If the tests pass, we are golden! If you would prefer to send the code and tests and not a PR, please just open up an issue!

---

<div class="post-metadata">

**Author:** ![Hal9000](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hal9000/32/1915_2.png) [@Hal9000](https://forum.elixirforum.com/u/Hal9000)\
**Post date:** [September 2, 2016, 8:12pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/10 "2016-09-02T20:12:29Z")

</div>

I cloned the repo and added two functions and two tests (which pass).

Not sure how to proceed. Tried a push - got this:

ERROR: Sorry, but @elixir-lang has blocked access to SSH keys created by  
some third-party applications. Your key was created before GitHub tracked  
keys created by applications, so we need your help.

[blah blah, omitted]

Duh?

Hal

---

<div class="post-metadata">

**Author:** ![OvermindDL1](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/32/2677_2.png) [@OvermindDL1](https://forum.elixirforum.com/u/OvermindDL1)\
**Post date:** [September 2, 2016, 10:33pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/11 "2016-09-02T22:33:53Z")

</div>

Look up in the github docs about ‘forking’ and ‘making a pull request’. Basically you will fork (copy) their repo into your own place. Clone that one down. Branch it with a decent name (“add\_rand” for example), make your changes, push those up to your repo, then in github submit a pull request on it (big button on the interface you cannot miss when you have a special feature branch like that).

I would give exact commands, but in a hurry. It is easy though once learned and github well documents it. 🙂

---

<div class="post-metadata">

**Author:** ![sztosz](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sztosz/32/1251_2.png) [@sztosz](https://forum.elixirforum.com/u/sztosz)\
**Post date:** [September 3, 2016, 6:15am UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/12 "2016-09-03T06:15:08Z")

</div>

It’s not that easy at all, everytime I do it I have to look up the docs 😃 But the docs are well written though 😉

---

<div class="post-metadata">

**Author:** ![Hal9000](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hal9000/32/1915_2.png) [@Hal9000](https://forum.elixirforum.com/u/Hal9000)\
**Post date:** [September 6, 2016, 11:06pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/13 "2016-09-06T23:06:08Z")

</div>

I do feel silly for not knowing that procedure. I will figure that out later,  
as I am pressed for time right now.

If anyone wants to take this on, the changes are very small. I’ll paste  
code (kernel.ex) and tests here.

Hal

```elixir
  @doc ~S"""
  `rand/0` returns a (pseudo)random number between 0 and 1.
  `rand/1` can take a range as a parameter, returning an integer
  from that range.
  """
  @spec rand() :: float
  def rand, do: :rand.uniform

  @spec rand(Range.t) :: integer
  def rand(n1..n2) when is_integer(n1) and is_integer(n2) do
    :rand.uniform(n2 - n1 + 1) + n1 - 1
  end

  test "rand/0" do
    x = rand()
    assert is_float(x)
    assert x >= 0.0
    assert x <= 1.0
  end

  test "rand/1" do
    n = rand(10..20)
    assert is_integer(n)
    assert n >= 10
    assert n <= 20
  end

```

---

<div class="post-metadata">

**Author:** ![josevalim](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/32/1787_2.png) [@josevalim](https://forum.elixirforum.com/u/josevalim)\
**Post date:** [September 7, 2016, 11:09am UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/14 "2016-09-07T11:09:32Z")

</div>

No worries, I have incorporated your changes to master here: [Add Kernel.rand/0 and Kernel.rand/1 · elixir-lang/elixir@786da1f · GitHub](https://github.com/elixir-lang/elixir/commit/786da1ffe075d50a26af885f4baf9589978c45c2)

---

<div class="post-metadata">

**Author:** ![hubertlepicki](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hubertlepicki/32/6822_2.png) [@hubertlepicki](https://forum.elixirforum.com/u/hubertlepicki)\
**Post date:** [September 7, 2016, 12:03pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/15 "2016-09-07T12:03:41Z")

</div>

Is it boring for me to repeat that you are increadibly good in making people contribute to Elixir? I mean, you don’t even have to know pull request flow to do so, awesome!

@Hal9000 for the future you may want to learn the procedure however. It’s both easier for the maintainer and you get some respect badge in the hood by being listed on official contributor’s list (as in here: [Contributors to elixir-lang/elixir · GitHub](https://github.com/elixir-lang/elixir/graphs/contributors)). If maintainer just copies the code, you are not listed (although in this particular case @josevalim was kind enough to mention you in the commit description!). Some people may care about this detail, others not, just letting you know 🙂

---

<div class="post-metadata">

**Author:** ![Hal9000](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hal9000/32/1915_2.png) [@Hal9000](https://forum.elixirforum.com/u/Hal9000)\
**Post date:** [September 7, 2016, 1:56pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/16 "2016-09-07T13:56:52Z")

</div>

Hubert speaks truth 😉@josevalim is awesome on more than one level.

I will certainly learn this procedure for next time.

As for contributors’ list – if I ever contribute 1,000 lines of code, I will  
care more. 🙂 I’m grateful to be mentioned, but I wouldn’t ask for mention  
for 20 or so LOC.

Cheers,  
Hal

---

<div class="post-metadata">

**Author:** ![OvermindDL1](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/32/2677_2.png) [@OvermindDL1](https://forum.elixirforum.com/u/OvermindDL1)\
**Post date:** [September 7, 2016, 2:21pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/17 "2016-09-07T14:21:14Z")

</div>

> [@Hal9000](#):
>
> Hubert speaks truth 😉@josevalim is awesome on more than one level

Yeah Jose is truly awesome. It is so pleasant to be around a BDFL that speaks so nicely. ^.^

---

<div class="post-metadata">

**Author:** ![hubertlepicki](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hubertlepicki/32/6822_2.png) [@hubertlepicki](https://forum.elixirforum.com/u/hubertlepicki)\
**Post date:** [September 7, 2016, 2:23pm UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/18 "2016-09-07T14:23:15Z")

</div>

I have a personal theory that in fact there are at least 3 @josevalim’s. You never know who is on the other end, since the visual contact is so rare. It’s physically impossible for one person to do so many awesome things.

---

<div class="post-metadata">

**Author:** ![sztosz](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sztosz/32/1251_2.png) [@sztosz](https://forum.elixirforum.com/u/sztosz)\
**Post date:** [February 1, 2017, 12:14am UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/19 "2017-02-01T00:14:10Z")

</div>

Hey does anyone knows what happend to this? I can’t find rand on master branch [elixir/lib/elixir/lib/kernel.ex at main · elixir-lang/elixir · GitHub](https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/kernel.ex) nor 1.4 branch it seems that it was added here: [Add Kernel.rand/0 and Kernel.rand/1 · elixir-lang/elixir@786da1f · GitHub](https://github.com/elixir-lang/elixir/commit/786da1ffe075d50a26af885f4baf9589978c45c2) and removed here: [Remove Kernel.rand/0 and Kernel.rand/1 · elixir-lang/elixir@8e2a1e5 · GitHub](https://github.com/elixir-lang/elixir/commit/8e2a1e58510dbefb5c707071fcba1584ba3b614f)

@josevalim: Was it meant to be reintroduced with `random` name instead of `rand` and somehow did not because someone people just forget things? Or was there more to the story of removal of that code?

---

<div class="post-metadata">

**Author:** ![josevalim](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/32/1787_2.png) [@josevalim](https://forum.elixirforum.com/u/josevalim)\
**Post date:** [February 1, 2017, 8:15am UTC](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518/20 "2017-02-01T08:15:35Z")

</div>

The reason is in the commit message, Enum.random/1 already provides the functionality, so we decided to stick with it.

[Next page](https://forum.elixirforum.com/t/random-based-on-rand-not-random/1518.md?page=2)
