-
-
Save cessor/29c3fc00667e7f95e35123778ffb8fa2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { performance } = require('perf_hooks'); | |
// LIZENZ: Gehört Horst Schneider | |
function Statistics(X) { | |
function Percentile(X, percent) { | |
this.value = function () { | |
const k = (X.length - 1) * percent; | |
const lower = Math.floor(k); | |
const upper = Math.ceil(k); | |
if(lower == upper){ | |
return X[k]; | |
} | |
const a = X[lower] * (upper - k); | |
const b = X[upper] * (k - lower); | |
return a + b; | |
}; | |
} | |
function Median(X) { | |
/* | |
// Or: | |
function Median (X) { | |
this.value = function () { | |
if(X.length % 2) { | |
const i = (X.length - 1) / 2; | |
return X[i]; | |
} | |
const i = X.length / 2; | |
return (X[i] + X[i - 1]) / 2; | |
} | |
} | |
*/ | |
this.value = function () { | |
return new Percentile(X, 0.5).value(); | |
}; | |
} | |
function Quartiles(X) { | |
this.Q1 = new Percentile(X, 0.25); | |
this.Q2 = new Percentile(X, 0.5); | |
this.Q3 = new Percentile(X, 0.75); | |
this.iqr = function () { | |
return this.Q3.value() - this.Q1.value(); | |
} | |
} | |
function Distribution(X) { | |
this.value = function () { | |
const n_items = X.length; | |
let sum_x = 0; | |
let square_sum_x = 0; | |
for(let i = 0; i < n_items; i++) { | |
const x = X[i]; | |
sum_x += x; | |
square_sum_x += x * x; | |
} | |
const mean = sum_x / n_items; | |
const variance = square_sum_x / n_items - mean * mean; | |
return { | |
" mean": mean, | |
" var": variance, | |
" std": Math.sqrt(variance) | |
}; | |
}; | |
} | |
this.describe = function () { | |
X.sort(function (a, b) { return a - b; }); | |
const report = new Distribution(X).value(); | |
const quartiles = new Quartiles(X); | |
return { | |
"count": X.length, | |
...report, | |
" min": X[0], | |
" 25%": quartiles.Q1.value(), | |
" 50%": quartiles.Q2.value(), | |
" 75%": quartiles.Q3.value(), | |
" max": X[X.length - 1] | |
} | |
} | |
} | |
function projection (item) { | |
return item ** 3 + item ** 2; | |
} | |
function with_map(data) { | |
return data.map(projection); | |
} | |
function with_for(data) { | |
const mapped = []; | |
const size = data.length; | |
for (let i = 0; i < size; i++) { | |
const item = data[i]; | |
mapped.push(item ** 3 + item ** 2); | |
} | |
return mapped; | |
} | |
function with_for_mc(data) { | |
const mapped = []; | |
const size = data.length; | |
for (let i = 0; i < size; i++) { | |
const item = data[i]; | |
mapped.push(projection(item)); | |
} | |
return mapped; | |
} | |
function with_foreach(data) { | |
const mapped = []; | |
for (let item of data) { | |
mapped.push(item ** 3 + item ** 2); | |
} | |
return mapped; | |
} | |
function with_foreach_mc(data) { | |
const mapped = []; | |
for (let item of data) { | |
mapped.push(projection(item)); | |
} | |
return mapped; | |
} | |
function with_generator(data) { | |
function* generator(data) { | |
for (let item of data) { | |
yield (item ** 3 + item ** 2); | |
} | |
} | |
return [...generator(data)]; | |
} | |
function Report(name, stats) { | |
function printHeadline () { | |
console.log(name); | |
console.log("=".repeat(name.length)); | |
}; | |
function printDescriptiveStatistics () { | |
const desc = stats.describe(); | |
for(let key in desc) { | |
console.log(` ${key}:\t${desc[key].toFixed(4)}`); | |
} | |
} | |
this.print = function () { | |
printHeadline(); | |
printDescriptiveStatistics(); | |
}; | |
} | |
function Random(count) { | |
this.numbers = function () { | |
return [...Array(count)].map(() => Math.random()); | |
}; | |
} | |
function Stopwatch (n_iterations, random) { | |
function _measure(func) { | |
const data = random.numbers(); | |
const start = performance.now(); | |
func(data); | |
return performance.now() - start; | |
} | |
this.measure = function (name, fn) { | |
const results = [...Array(n_iterations)].map(() => _measure(fn)); | |
return new Report( | |
name, | |
new Statistics(results) | |
); | |
} | |
} | |
const SIZE = 1e6; | |
const N_ITERATIONS = 1000; | |
const stopwatch = new Stopwatch(N_ITERATIONS, new Random(SIZE)); | |
console.log(); | |
console.log(`Projection of ${SIZE} random numbers using...`) | |
console.log(); | |
const trials = new Map([ | |
['...for', with_for], | |
['...for, but with a function call', with_for_mc], | |
['...foreach', with_foreach], | |
['...foreach, but with a function call', with_foreach_mc], | |
['...map', with_map], | |
['...a generator', with_generator] | |
]); | |
for(let [name, func] of trials) { | |
stopwatch.measure(name, func).print(); | |
console.log(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment