Code Monkey home page Code Monkey logo

random's Introduction

random

Seedable random number generator supporting many common distributions.

NPM Build Status Prettier Code Formatting

Welcome to the most random module on npm! ๐Ÿ˜œ

Highlights

  • Simple API (make easy things easy and hard things possible)
  • TypeScript support
  • Supports node >= 14 and browser
  • Seedable based on entropy or user input
  • Plugin support for different pseudo random number generators (PRNGs)
  • Sample from many common distributions
    • uniform, normal, poisson, bernoulli, etc
  • Validates all user input
  • Integrates with seedrandom

Install

npm install --save random
# or
yarn add random
# or
pnpm add random

Note: this package uses ESM and no longer provides a CommonJS export. See here for more info on how to use ESM modules.

Usage

import random from 'random'

// quick uniform shortcuts
random.float((min = 0), (max = 1)) // uniform float in [ min, max )
random.int((min = 0), (max = 1)) // uniform integer in [ min, max ]
random.boolean() // true or false

// uniform distribution
random.uniform((min = 0), (max = 1)) // () => [ min, max )
random.uniformInt((min = 0), (max = 1)) // () => [ min, max ]
random.uniformBoolean() // () => [ false, true ]

// normal distribution
random.normal((mu = 0), (sigma = 1))
random.logNormal((mu = 0), (sigma = 1))

// bernoulli distribution
random.bernoulli((p = 0.5))
random.binomial((n = 1), (p = 0.5))
random.geometric((p = 0.5))

// poisson distribution
random.poisson((lambda = 1))
random.exponential((lambda = 1))

// misc distribution
random.irwinHall(n)
random.bates(n)
random.pareto(alpha)

For convenience, several common uniform samplers are exposed directly:

random.float() // 0.2149383367670885
random.int(0, 100) // 72
random.boolean() // true

// random array item
random.choice([1, true, 'foo']) // 'foo'

All distribution methods return a thunk (function with no params), which will return a series of independent, identically distributed random variables from the specified distribution.

// create a normal distribution with default params (mu=1 and sigma=0)
const normal = random.normal()
normal() // 0.4855465422678824
normal() // -0.06696771815439678
normal() // 0.7350852689834705

// create a poisson distribution with default params (lambda=1)
const poisson = random.poisson()
poisson() // 0
poisson() // 4
poisson() // 1

Note that returning a thunk here is more efficient when generating multiple samples from the same distribution.

You can change the underlying PRNG or its seed as follows:

import seedrandom from 'seedrandom'

// change the underlying pseudo random number generator
// by default, Math.random is used as the underlying PRNG
random.use(seedrandom('foobar'))

// create a new independent random number generator (uses seedrandom under the hood)
const rng = random.clone('my-new-seed')

// create a second independent random number generator and use a seeded PRNG
const rng2 = random.clone(seedrandom('kittyfoo'))

// replace Math.random with rng.uniform
rng.patch()

// restore original Math.random
rng.unpatch()

You can also instantiate a fresh instance of Random:

import { Random } from 'random'
import seedrandom from 'seedrandom'

const rng = new Random()
const rng2 = new Random(seedrandom('tinykittens'))

API

Table of Contents

Seedable random number generator supporting many common distributions.

Defaults to Math.random as its underlying pseudorandom number generator.

Type: function (rng)

  • rng (RNG | function) Underlying pseudorandom number generator. (optional, default Math.random)

Type: function ()


  • See: RNG.clone

Creates a new Random instance, optionally specifying parameters to set a new seed.

Type: function (args, seed, opts): Random

  • args ...any
  • seed string? Optional seed for new RNG.
  • opts object? Optional config for new RNG options.

Sets the underlying pseudorandom number generator used via either an instance of seedrandom, a custom instance of RNG (for PRNG plugins), or a string specifying the PRNG to use along with an optional seed and opts to initialize the RNG.

Type: function (args)

  • args ...any

Example:

import random from 'random'

random.use('example_seedrandom_string')
// or
random.use(seedrandom('kittens'))
// or
random.use(Math.random)

Patches Math.random with this Random instance's PRNG.

Type: function ()


Restores a previously patched Math.random to its original value.

Type: function ()


Convenience wrapper around this.rng.next()

Returns a floating point number in [0, 1).

Type: function (): number


Samples a uniform random floating point number, optionally specifying lower and upper bounds.

Convence wrapper around random.uniform()

Type: function (min, max): number

  • min number Lower bound (float, inclusive) (optional, default 0)
  • max number Upper bound (float, exclusive) (optional, default 1)

Samples a uniform random integer, optionally specifying lower and upper bounds.

Convence wrapper around random.uniformInt()

Type: function (min, max): number

  • min number Lower bound (integer, inclusive) (optional, default 0)
  • max number Upper bound (integer, inclusive) (optional, default 1)

Samples a uniform random integer, optionally specifying lower and upper bounds.

Convence wrapper around random.uniformInt()

Type: function (min, max): number

  • min number Lower bound (integer, inclusive) (optional, default 0)
  • max number Upper bound (integer, inclusive) (optional, default 1)

Samples a uniform random boolean value.

Convence wrapper around random.uniformBoolean()

Type: function (): boolean


Samples a uniform random boolean value.

Convence wrapper around random.uniformBoolean()

Type: function (): boolean


Returns an item chosen uniformly at trandom from the given array.

Convence wrapper around random.uniformInt()

Type: function choice <T> (array: Array<T>): T | undefined

  • array Array Array of items to sample from

Generates a Continuous uniform distribution.

Type: function (min, max): function

  • min number Lower bound (float, inclusive) (optional, default 0)
  • max number Upper bound (float, exclusive) (optional, default 1)

Generates a Discrete uniform distribution.

Type: function (min, max): function

  • min number Lower bound (integer, inclusive) (optional, default 0)
  • max number Upper bound (integer, inclusive) (optional, default 1)

Generates a Discrete uniform distribution, with two possible outcomes, true or `false.

This method is analogous to flipping a coin.

Type: function (): function


Generates a Normal distribution.

Type: function (mu, sigma): function

  • mu number Mean (optional, default 0)
  • sigma number Standard deviation (optional, default 1)

Generates a Log-normal distribution.

Type: function (mu, sigma): function

  • mu number Mean of underlying normal distribution (optional, default 0)
  • sigma number Standard deviation of underlying normal distribution (optional, default 1)

Generates a Bernoulli distribution.

Type: function (p): function

  • p number Success probability of each trial. (optional, default 0.5)

Generates a Binomial distribution.

Type: function (n, p): function

  • n number Number of trials. (optional, default 1)
  • p number Success probability of each trial. (optional, default 0.5)

Generates a Geometric distribution.

Type: function (p): function

  • p number Success probability of each trial. (optional, default 0.5)

Generates a Poisson distribution.

Type: function (lambda): function

  • lambda number Mean (lambda > 0) (optional, default 1)

Generates an Exponential distribution.

Type: function (lambda): function

  • lambda number Inverse mean (lambda > 0) (optional, default 1)

Generates an Irwin Hall distribution.

Type: function (n): function

  • n number Number of uniform samples to sum (n >= 0) (optional, default 1)

Generates a Bates distribution.

Type: function (n): function

  • n number Number of uniform samples to average (n >= 1) (optional, default 1)

Generates a Pareto distribution.

Type: function (alpha): function

  • alpha number Alpha (optional, default 1)

Todo

  • Distributions

    • uniform
    • uniformInt
    • uniformBoolean
    • normal
    • logNormal
    • chiSquared
    • cauchy
    • fischerF
    • studentT
    • bernoulli
    • binomial
    • negativeBinomial
    • geometric
    • poisson
    • exponential
    • gamma
    • hyperExponential
    • weibull
    • beta
    • laplace
    • irwinHall
    • bates
    • pareto
  • Generators

    • pluggable prng
    • port more prng from boost
    • custom entropy
  • Misc

    • browser support via rollup
    • basic docs
    • basic tests
    • test suite
    • initial release!
    • typescript support

Related

  • d3-random - D3's excellent random number generation library.
  • seedrandom - Seedable pseudo random number generator.
  • random-int - For the common use case of generating uniform random ints.
  • random-float - For the common use case of generating uniform random floats.
  • randombytes - Random crypto bytes for Node.js and the browser.

Credit

Thanks go to Andrew Moss for the TypeScript port and for helping to maintain this package!

Shoutout to Roger Combs for donating the random npm package for this project!

Lots of inspiration from d3-random (@mbostock and @svanschooten).

Some distributions and PRNGs are ported from C++ boost::random.

License

MIT ยฉ Travis Fischer

Support my OSS work by following me on twitter twitter

random's People

Contributors

agmoss avatar transitive-bullshit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

random's Issues

Unexpected failsafe in Random constructor

Hello!

I noticed that Random constructor just ignores argument if it is not RNG without any error message:

this.use(new RNGMathRandom())

Maybe it will be more helpful to throw Error or raise some console.error message in this case, to not mislead users.

Second thing is that README suggests use following code to specify seed:

import { Random } from 'random'
import seedrandom from 'seedrandom'

const rng = new Random()
const rng2 = new Random(seedrandom('tinykittens'))

And this isn't correct because of that check in constructor.

Best regards,
ProgMiner

New Feature Request: Get HEX randomly by length and letter type.

Hello.

I'm new to programming.

I really like this random app.

I need to generate a HEX (Hexadecimal) string of specific length.

But I see I didn't find this function random.hex(length, options) in random.

It would be great to be able to generate HEX values โ€‹โ€‹of custom length and letter type.

For example:

let get40 = random.hex(40, both); // options: capital, lowercase, both.

console.log(get40); // 0397032E0f12958AC8EC58728018e299e883254b

Thank you for your attention.

Consider Publishing as ES5

I'm just trying to use your module but it seems to require some dependency called esm โ€”ย I think a better solution might be to just transpile to ES5 compatible code so that users can just require('random') or import 'random' in node and browserify.

uniform-int (and likely other distributions) are not as uniform as possible

uniform-int currently functions by stretching the output range of the RNG into the desired range. However, this is not strictly correct as it depends on the output size of the RNG. For instance, with a small-scale example, if the RNG only outputs 16 bits and we're generating a number from 0 to 5:

>>> collections.Counter(i * 6 // 0xffff for i in range(0xffff))
Counter({0: 10923, 2: 10923, 4: 10923, 1: 10922, 3: 10922, 5: 10922})

We can run a simulation to see the effect of this as well:

const random = require("random")

const hist = new Map();

for (let i = 0; i < 20000000; i++) {
    const n = random.int(0, 5);
    hist.set(n, (hist.get(n) || 0) + 1);
}

and we get:

Map(6) {
  4 => 3334526,
  5 => 3333539,
  3 => 3334684,
  1 => 3331604,
  0 => 3333306,
  2 => 3332341
}

In order to get a truly uniform distribution, the generator needs to instead:

  • operate by generating bits with a uniform distribution (it's likely that Math.random will at least be uniform over 64 bits, so it's possible to generate 64 bits at a time).
  • generate enough bits to hold the max value
  • if the generated number is > max value, discard and try again

https://github.com/python/cpython/blob/8a0d9a6bb77a72cd8b9ece01b7c1163fff28029a/Lib/random.py#L235-L243 has an example of how it works.

Cannot import successfully

Cannot import successfully. How do I solve this?

I'm using it like so.

import random from 'random'

//...

const get = () => {
    const num = random.uniformInt(0, 100)();
    return num;
}

but it shows me this:

ERROR in ./node_modules/random/dist/esm/index.esm.js 1:0-30
Module not found: Error: Can't resolve './random' in 'myprojects\project\node_modules\random\dist\esm'
Did you mean 'random.js'?
BREAKING CHANGE: The request './random' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

I tried these but didnt work:

import random from 'random.js'
import random from 'random.ejs'
import random from 'random.esm.js'
import random from 'random.mjs'

Exposing Random constructor

Hello!

First of all, thank you so much for your work! :D

I started a fun project that uses your module. Is there any reason why are you not exposing the Random class? I would like to instantiate different Objects that have different seeds and it would be useful to instantiate random generators.

Thank you in advance

new feature request: improve choice

I have a request: Can the choice() function be enhanced to retrieve more than one option?

random.choices(data: array, choices: number, isUnique: boolean = true)

example:

random.choices([1, true, 'foo'], 3) //return: true, 'foo', 1

random.choices([1, true, 'foo'], 3, false) //return: true, 'foo', 'foo'

random.int bug with unexpected negative random numbers

Here is my code:

index.ts:

import random from 'random';

const min = 0;
const max = 14206147658

for (let i = 0; i < 100; i = i+1) {
  const randomInt = random.int(min, max);
  console.log(`${i}: random: ${randomInt}`);
}

Here is a sample of my result:

0: random: 727406658
1: random: -579739191
2: random: -42082040
3: random: -915337893
4: random: 1667450201
5: random: 120576257
6: random: -839908019
7: random: 626427272
8: random: 345808248
9: random: 1928860574
10: random: 241466404
...

Why am I getting negative results?

Security: breaks when CSP is enabled

When runing in a browser, with a Content Security Policy (CSP) enabled, which does not allow eval (which is every decent policy), this package breaks the application.

I receive the following error in Chromium:

EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self'".

    at eval (<anonymous>)
    at seedrandom.js:32
    at Object../node_modules/seedrandom/seedrandom.js (seedrandom.js:25)
    at Object../node_modules/seedrandom/index.js (index.js:51)
    at Object../node_modules/random/dist/rng-factory.js (rng-factory.js:1)
    at Object../node_modules/random/dist/random.js (random.js:4)

It seems that the eval() comes from seedrandom package and it has been fixed a few months ago there:
davidbau/seedrandom#64
davidbau/seedrandom#65

Could you please upgrade seedrandom to the latest version?

Predictable pseudo random number

I expected this module to return the same sequence of random numbers if seeded with the same value. But it seems completely unpredictable. I'm I missing something?

const rng = random.clone(seed).uniform();

rng();
rng();
rng();

I would've expected the three rnd() calls to return the same random numbers every time.

Stopped working for version 3.0.0

I have some JS code, run in node, which was working in 2.2 and now is not. Previously I had:

const random = require('random')
...
const power = random.normal(27.545, 2.182)
...
const v = power()

Now I get

Uncaught TypeError: random.normal is not a function

So I changed to

const random = require('random').default

but now

> power()
Uncaught TypeError: Cannot read property 'next' of undefined
    at Random.next (D:\temp\ser\node_modules\random\dist\random.js:56:31)
    at exports.default (D:\temp\ser\node_modules\random\dist\distributions\normal.js:9:24)

so I had to add

random.use(Math.random)

as part of the initialization.

Please could you advise: Am I doing the right thing? It would be great if this could make it into the docs. I assume this all works as per the docs in Typescript but I am not allowed to use that at the moment.

new Random vs random.clone

Hi!

First, thanks for this super cool library.

I just ran into an issue which may just be an issue of the documentation.

When working with seeds, I expected new Random(seedrandom('tinykittens')) to work the same as random.use(seedrandom('tinykittens')) or random.clone(seedrandom('tinykittens')).

But appearently new Random doesn't seed correctly?

console.log('rng test random..')
for (let i=0; i<3; ++i) {
	const prng = new Random(seedrandom('my-seed'))
	console.log(prng.float())
}
// =>
// 0.6724578711199012
// 0.014330871501025522
// 0.16677254682291287

If this is expected behaviour then I think the documentation should be adjusted near the text You can also instantiate a fresh instance of Random.

Several functions result in an error for all arguments

bernoulli()
binomial()
geometric()
irwinHall()
bates()
pareto()

all throw errors for all inputs, including defaults.

For example:

// Running this
const random = require('random');
const foo = random.bernoulli(0.4);
foo();

// results in
Error: invalid number of arguments to "ow"
    at Object.apply (C:\Users\Andy.Steinberg\Code\test\node_modules\ow-lite\index.js:95:15)
    at exports.default (C:\Users\Andy.Steinberg\Code\test\node_modules\random\dist\distributions\bernoulli.js:16:52)
    at Random.bernoulli (C:\Users\Andy.Steinberg\Code\test\node_modules\random\dist\random.js:369:38)
    at Object.<anonymous> (C:\Users\Andy.Steinberg\Code\test\tester.js:3:20)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)

All of the listed functions result in the same error.

PRNG vs RNG

When I try to compile the code from the example using typescript

import { Random } from 'random'
import seedrandom from 'seedrandom'

const rng = new Random()
const rng2 = new Random(seedrandom('tinykittens'))

I get the following error
TS2345: Argument of type 'PRNG' is not assignable to parameter of type 'RNG'.

Open call for ideas + contributors

Hello beautiful software peoples,

imho, JavaScript has been in sore need of a rock solid random module for some time. I tried to find something robust and comprehensive ala boost::random, but the closest I could find were d3-random and seedrandom.

After @rcombs generously donated the npm module random to me, I wanted to try and set a baseline for the API and functionality that exists in this repo today. It's my hope that this will grow, but to get there I think it's important to ask for feedback from the community early on.

I'd like to extend an open invitation to anyone who sees the potential in this module to elicit feedback and/or join as collaborators.

To be clear, I definitely still see a lot of value in one-off modules like random-int and random-normal for the 95% use cases, but I think having a common core for supporting more advanced scenarios will be really useful in promoting scientific computing with JavaScript.

How to specify a seed

I expected that after setting the same seed, the behavior of both clones would be the same. Unfortunately the following test fails.

import random from "random"

describe('random', () => {
  it('should be predictable', () => {
    const rand1 = random.clone("abc");
    const rand2 = random.clone("abc");
    
    expect(rand1.float()).toEqual(rand2.float());
  });
});

Am I using clone incorrectly?

I'm pretty close to the example from the readme:

...
// create a new independent random number generator (uses seedrandom under the hood)
const rng = random.clone('my-new-seed')
...

Missing esm build file

Using 3.0.3 I see an error with import random from "random" in a Create React App project.
It says:

./node_modules/random/dist/esm/index.js
Module not found: Can't resolve './random' in './node_modules/random/dist/esm'

I've double checked: there is an index.js there, it tries to require('./random').default but fails because there isn't any random.js file in there :(

I believe it might be connected to #19

Add random.choice

Just like python random, making random.choice is a pretty good thing. just for a simplicity.

Example :
array : ["a", "b"]
Instead of doing

array[random.int(0,1)] // return "a"

isn't it better if you could do :

random.choice(array) // return "a"

I know some of you'll like "you can make it yourself". But isn't this why this module created?

random.normal returns negative number..

Seemingly fairly easy to break..

const random = require('random');

let mean = 300
let sd = 100

let res = 1
let counter = 0;
while (res>0) {
    const s = random.normal(mean, sd)
     res = Math.round(s())
     counter = counter+1;
}
console.log("broke after num tries:", counter)

installation

Hi! I need help for install package. During installation I get this error :

> node postinstall || echo "ignore"

In riga:1 car:18
+ node postinstall || echo "ignore"
+                  ~~
Il token '||' non รจ un separatore di istruzioni valido in questa versione.     
    + CategoryInfo          : ParserError: (:) [], 
ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidEndOfLine
 
[            ......] \ postinstall: info lifecycle [email protected]~postinstall: 
[            ......] \ postinstall: info lifecycle [email protected]~postinstall: 
[            ......] \ postinstall: info lifecycle [email protected]~postinstall: 
[            ......] \ postinstall: info lifecycle [email protected]~postinstall: 
[            ......] \ postinstall: info lifecycle [email protected]~postinstall: 
[            ......] \ postinstall: info lifecycle [email protected]~postinstall: 
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] postinstall: `node postinstall || echo "ignore"`       
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\sdelg\AppData\Roaming\npm-cache\_logs\2020-04-20T09_12_37_454Z-debug.log

I have already tried to reinstall nodeJS, delete node_modules and package-lock.json and redo npm install
Do you have any idea?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.