Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added normal for generating normally distributed numbers. added randi…

…nt to generate numbers between min and max. add demos/ to show how some of the functions can be used.
  • Loading branch information...
commit 63685b7577693091e8458e298e564dd88140ae7f 1 parent 6ddab2c
Jillis ter Hove BruceJillis authored
Showing with 208 additions and 1 deletion.
  1. +6 −0 README.md
  2. +72 −0 demos/normal.html
  3. +102 −0 demos/randint.html
  4. +28 −1 mathplus.js
6 README.md
View
@@ -10,6 +10,12 @@ Everything lives under the M object. Functions include:
- factorial: Returns NaN for negative numbers. Thanks to @Kambfhase for passing along @nikic's significant speed-up! Recursion may be elegant but it's slow.
- limit: Provides an approximation. Works in some cases with +/- Infinity. Needs some additional tweaking.
- derivative: Given f and x, will provide an approximation of the derivative of function f at point x. Round the result to get integers for derivatives of common functions, e.g. of f(x) = 3*x.
+- normal: Given mean and deviation returns random values from a normal distribution.
+- randint: Given a min, and max returns a random integer in the range: min <= result <= max
+
+## Demos
+
+The demos/ subdirectory contains a few demos that demonstrate the uses of the various functions.
## Vectors
72 demos/normal.html
View
@@ -0,0 +1,72 @@
+<html>
+ <head>
+ <script type="text/javascript" src="../mathplus.js"></script>
+ </head>
+ <body>
+ <script type="text/javascript">
+ // this demo draws a random normal distributed point cloud on a canvas
+
+ // generate a normal(mean, deviation) cluster around x, y of amount points
+ function cluster(x, y, mean, deviation, amount) {
+ var result = new Array()
+ for(var i = 0; i <= amount; i++ ) {
+ result.push({
+ 'x': x + M.normal(mean, deviation),
+ 'y': y + M.normal(mean, deviation),
+ });
+ }
+ return result;
+ }
+
+ // draw a small rect (a dot)
+ function dot(ctx, x, y) {
+ ctx.fillStyle = "black";
+ ctx.fillRect(x, y, 1, 1);
+ }
+
+ // main drawing function
+ function draw() {
+ // get the canvas
+ var canvas = document.getElementById("canvas");
+ var ctx = canvas.getContext("2d");
+ ctx.clearRect(0, 0, 300, 300);
+
+ // get values from DOM
+ var x = parseInt(document.getElementById('x').value);
+ var y = parseInt(document.getElementById('y').value);
+ var mean = parseInt(document.getElementById('mean').value);
+ var deviation = parseInt(document.getElementById('deviation').value);
+ var amount = parseInt(document.getElementById('amount').value);
+
+ // compute cluster
+ var points = cluster(x, y, mean, deviation, amount);
+ // draw cluster
+ for(var i = 0; i < points.length; i++ ) {
+ dot(ctx, points[i].x, points[i].y);
+ }
+ }
+ window.onload = draw;
+ </script>
+ <canvas id="canvas" width="300" height="300" style="border: 1px solid grey;" ></canvas>
+ <fieldset>
+ <legend>Parameters</legend>
+ <div>
+ <label for="x">X, Y: </label>
+ <input id="x" value="150" size="1"/>, <input id="y" value="150" size="1"/>
+ </div>
+ <div>
+ <label for="mean">Mean:</label>
+ <input id="mean" value="-10" size="1"/>
+ </div>
+ <div>
+ <label for="deviation">Deviation:</label>
+ <input id="deviation" value="20" size="1"/>
+ </div>
+ <div>
+ <label for="amount">Amount:</label>
+ <input id="amount" value="1000" size="1"/>
+ </div>
+ <button onclick="draw()" >Draw</button>
+ </fieldset>
+ </body>
+</html>
102 demos/randint.html
View
@@ -0,0 +1,102 @@
+<html>
+ <head>
+ <script type="text/javascript" src="../mathplus.js"></script>
+ </head>
+ <body>
+ <H1>JavaScript Math.random() Test</H1>
+ <strong>Testing from min to max. Running iterations tests. </strong>
+ <fieldset>
+ <legend>Parameters</legend>
+ <div>
+ <label for="min">Min:</label>
+ <input id="min" value="1" />
+ </div>
+ <div>
+ <label for="max">Max:</label>
+ <input id="max" value="10" />
+ </div>
+ <div>
+ <label for="iterations">Iterations:</label>
+ <input id="iterations" value="5000" />
+ </div>
+ <button onclick="draw()" >Draw</button>
+ </fieldset>
+
+ <script type="text/javascript">
+ function histogram(el, hist, min, max, itt) {
+ var content = '';
+ for (var i=min; i <= max; i++) {
+ //document.write (i + ': ');
+ content += i + ': ';
+ for (var j=0; j < hist[i]; j=j+(itt/500)) {
+ //document.write ('|');
+ content += '|'
+ }
+ //document.write (' ' + Math.round (hist[i]*1000/itt)/10 + '%<br>');
+ content += ' ' + Math.round (hist[i]*1000/itt)/10 + '%\n';
+ }
+ document.getElementById(el).innerHTML = '<pre>' + content + '</pre>';
+ }
+
+ // main drawing function
+ function draw() {
+ // get value from the DOM
+ var min = parseInt(document.getElementById('min').value);
+ var max = parseInt(document.getElementById('max').value);
+ var iterations = parseInt(document.getElementById('iterations').value);
+
+ // make a histogram of randint
+ var hist = new Array();
+ for (var k=min; k <= max; k++) {
+ hist[k] = 0;
+ }
+ for (var i=0; i < iterations; i++) {
+ hist[M.randint(min, max)]++;
+ }
+ histogram('randint', hist, min, max, iterations);
+
+ // make a histogram of variation 1
+ var hist = new Array();
+ for (var k=min; k <= max; k++) {
+ hist[k] = 0;
+ }
+ for (var i=0; i < iterations; i++) {
+ hist[Math.round(Math.random() * (max - min) + min)]++;
+ }
+ histogram('adhoc', hist, min, max, iterations);
+
+ // make a histogram of variation 2
+ var hist = new Array();
+ for (var k=min; k <= max; k++) {
+ hist[k] = 0;
+ }
+ for (var i=0; i < iterations; i++) {
+ hist[Math.ceil(Math.random() * (max - min + 1) + min - 1)]++;
+ }
+ histogram('ceil', hist, min, max, iterations);
+ }
+ window.onload = draw;
+ </script>
+
+ <div>
+ <strong>M.randint()</strong>
+ <div id="randint"></div>
+ </div>
+
+ <div>
+ <strong>Ad Hoc: Math.round(Math.random() * (max - min) + min)</strong>
+ <br/>
+ <em>note: Notice the values "fall-off" near the limits of the range.</em>
+ <div id="adhoc"></div>
+ </div>
+
+ <div>
+ <strong>Ceil: Math.ceil(Math.random() * (max - min + 1) + min - 1)</strong>
+ <br/>
+ <em>note: There is a minute possibility that this function will return (min-1). This is why floor is a better choice.</em>
+ <div id="ceil"></div>
+ </div>
+
+ <p>Based on work by Andrew Penry: <a href="http://www.shawnolson.net/a/789/make-javascript-mathrandom-useful.html">Make JavaScript Math.random() useful</a>, <a href="http://thepenry.net/jsrandom.php">JavaScript Math.random() Test</a></p>
+ </body>
+</html>
29 mathplus.js
View
@@ -95,13 +95,40 @@ var M = {
}
// make sure rangeEnd > rangeStart
- if (rangeEnd < rangeStart) {
+ if (rangeEnd < rangeStart) {
var tmp = rangeEnd;
rangeEnd = rangeStart;
rangeStart = tmp;
}
return ((Math.random() * (rangeEnd - rangeStart)) + rangeStart);
},
+ // generate random integers: min <= result <= max
+ // see: Andrew Penry's http://www.shawnolson.net/a/789/make-javascript-mathrandom-useful.html
+ 'randint': function random(min, max) {
+ if (typeof min != "number" && !(min instanceof Number)) {
+ throw new RangeError("min must be a valid number >= 0")
+ }
+ if (typeof max != "number" && !(max instanceof Number)) {
+ throw new RangeError("max must be a valid number >= 0")
+ }
+ return Math.floor(Math.random()*(max-min+1)+min)
+ },
+ // N(m,s)
+ // returns random number with normal (gaussian) distribution: mean=m, std dev=s using the box-muller transformation
+ // see: http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
+ 'normal': function normal(mean, deviation) {
+ if (typeof mean != "number" && !(mean instanceof Number)) {
+ throw new RangeError("mean must be a valid number")
+ }
+ if (typeof deviation != "number" && !(deviation instanceof Number)) {
+ throw new RangeError("deviation must be a valid number > 0")
+ }
+ var x = this.random(0, 1);
+ var y = this.random(0, 1);
+ var z1 = Math.sqrt(-2*Math.log(x))*Math.cos(2*Math.PI*y);
+ // var z2 = Math.sqrt(-2*Math.log(x))*Math.sin(2*Math.PI*y);
+ return (z1 * deviation) + mean;
+ },
// NOTE: The number is always converted to an integer
'factorial': function factorial(num) {
num = parseInt(num)
Please sign in to comment.
Something went wrong with that request. Please try again.