This JavaScript program demonstrates how to generate and graph a uniform distribution. The uniform distribution is generated in the range [0,1].
<!DOCTYPE html> <html> <head> <title>XoaX.net's Javascript</title> <script type="text/javascript" src="GraphingAUniformDistribution.js"></script> </head> <body onload="Initialize()"> <div style="width:858px;height:430px;"> <div style="width:58px;height:430px;float:left;"> <input id="idHighY" type="text" size="9" style="width:50px;height:16px;"/> <div style="width:58px;height:356px;"></div> <input id="idLowY" type="text" size="9" style="width:50px;height:16px;"/> </div> <canvas id="idCanvas" width="800" height ="400" style="background-color: #F0F0F0;float:left;"></canvas> <div style="width:800px;height:22px;float:left;"> <input id="idLowX" type="text" size="9" style="width:50px;height:16px;float:left;"/> <div style="width:684px;height:22px;float:left;"></div> <input id="idHighX" type="text" size="1" value="1.2" style="width:50px;height:16px;float:left;"/> </div> </div> </body> </html>
class CUniformDistribution {
#mdaX;
#mdGraphWidth = 1.2;
constructor(iCount) {
// This generates a sorted array of the sample values of the distribution
// This is a uniform distribution from 0 to 1
this.#mdaX = new Array(iCount);
for (let i = 0; i < iCount; ++i) {
this.#mdaX[i] = Math.random();
// Insertion sort each point after it is added
let j = i;
while (j > 0 && this.#mdaX[j] < this.#mdaX[j - 1]) {
let dSwap = this.#mdaX[j];
this.#mdaX[j] = this.#mdaX[j - 1];
this.#mdaX[j - 1] = dSwap;
--j;
}
}
}
Mean() {
let dMean = 0;
for (let i = 0; i < this.#mdaX.length; ++i) {
dMean += this.#mdaX[i]/this.#mdaX.length;
}
return dMean;
}
StandardDeviation() {
return Math.sqrt(this.Variance());
}
Variance() {
let dMean = this.Mean();
let dVariance = 0;
for (let i = 0; i < this.#mdaX.length; ++i) {
dVariance += Math.pow(this.#mdaX[i] - dMean, 2)/this.#mdaX.length;
}
return dVariance;
}
PixelXToGraphX(dPixelX, iCanvasWidth) {
// Half the size should map to the mean
let dHalfWidth = this.#mdGraphWidth/2;
let dMean = this.Mean();
let dT = ((dPixelX + .5)/iCanvasWidth)*this.#mdGraphWidth - dHalfWidth + dMean;
return dT;
}
Graph(qContext, dBarWidthInPixels) {
qContext.fillStyle = "#606060";
// Outline properties
qContext.strokeStyle = "#F0F0F0";
qContext.lineWidth = "1";
// This is the basic transformation to flip the y-axis
qContext.transform(1, 0, 0, -1, 0, qContext.canvas.height);
// The canvas width and height in pixels or pixels per canvas
let iW = qContext.canvas.width;
let iH = qContext.canvas.height;
// The canvas graph width: 1.2
let dGraphW = this.#mdGraphWidth;
// Pixel width in graph units = graph width / pixels per canvas width
let dPixW = dGraphW/iW;
// Bar width in pixels / pixels per canvas width
let dBarsPerWidth = iW/dBarWidthInPixels;
// The width of a bar in values
let dBarWidth = dBarWidthInPixels*dPixW;
// The middle bar is centered on zero
// Find the start of the first bar and continue from there until all of them are drawn
let dStartOfFirstBarPix = iW/2 - dBarWidthInPixels/2 - dBarWidthInPixels*Math.ceil(dBarsPerWidth/2);
let dStartOfCurrBarPix = dStartOfFirstBarPix;
let dStartOfCurrBarValue = this.PixelXToGraphX(dStartOfCurrBarPix, iW);
let iIndexOfNextPoint = 0;
// Get to the first point that is in the range of the first bar.
while (iIndexOfNextPoint < this.#mdaX.length && dStartOfCurrBarValue > this.#mdaX[iIndexOfNextPoint]) {
++iIndexOfNextPoint;
}
let iaBins = new Array();
while (iIndexOfNextPoint < this.#mdaX.length && dStartOfCurrBarPix < iW) {
let dEndOfCurrBarPix = dStartOfCurrBarPix + dBarWidthInPixels;
let dEndOfCurrBarValue = this.PixelXToGraphX(dEndOfCurrBarPix, iW);
let iIndexOfEnd = iIndexOfNextPoint;
while (iIndexOfEnd < this.#mdaX.length && dEndOfCurrBarValue > this.#mdaX[iIndexOfEnd]) {
++iIndexOfEnd;
}
// The number of points in the bin
iaBins.push(iIndexOfEnd - iIndexOfNextPoint);
// The increment for the bar
dStartOfCurrBarPix = dEndOfCurrBarPix;
// Increment for the points
iIndexOfNextPoint = iIndexOfEnd;
}
// Get the size of the largest bin
let iLargestBinSize = 0;
for (let i = 0; i < iaBins.length; ++i) {
if (iLargestBinSize < iaBins[i]) {
iLargestBinSize = iaBins[i];
}
}
// Make the height of the graph 20% higher than the largest bin size.
let dMaxY = iLargestBinSize*1.2;
let iBinIndex = 0;
dStartOfCurrBarPix = dStartOfFirstBarPix;
// Draw the bars of the graph
while (iBinIndex < iaBins.length && dStartOfCurrBarPix < iW) {
let dEndOfCurrBarPix = dStartOfCurrBarPix + dBarWidthInPixels;
let dRectHeight = iaBins[iBinIndex];
qContext.fillRect(dStartOfCurrBarPix, 0, dBarWidthInPixels, (dRectHeight/dMaxY)*iH);
// Draw the half pixel width outline in the background color to frame the bars
qContext.strokeRect(dStartOfCurrBarPix, 0, dBarWidthInPixels, (dRectHeight/dMaxY)*iH);
// The increment for the bar
dStartOfCurrBarPix = dEndOfCurrBarPix;
++iBinIndex;
}
// Fill in the bounds
let qLowYElement = document.getElementById("idLowY");
qLowYElement.value = 0;
let qHighYElement = document.getElementById("idHighY");
qHighYElement.value = dMaxY.toFixed(1);
let qLowXElement = document.getElementById("idLowX");
qLowXElement.value = this.PixelXToGraphX(-.5, iW).toFixed(3);
let qHighXElement = document.getElementById("idHighX");
qHighXElement.value = this.PixelXToGraphX(iW-.5, iW).toFixed(3);
}
}
function Initialize() {
var qCanvas = document.getElementById("idCanvas");
var qContext = qCanvas.getContext("2d");
var qDist = new CUniformDistribution(10000);
qDist.Graph(qContext, 5);
}
© 20072026 XoaX.net LLC. All rights reserved.