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...
1 parent 6ddab2c commit 63685b7577693091e8458e298e564dd88140ae7f @BruceJillis BruceJillis committed Jan 23, 2011
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
View
6 README.md
@@ -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
View
72 demos/normal.html
@@ -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>
View
102 demos/randint.html
@@ -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>
View
29 mathplus.js
@@ -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)

0 comments on commit 63685b7

Please sign in to comment.