-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
120 lines (99 loc) · 2.19 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
'use strict';
/**
* We need to specify a cache size to be enough for all needed calculations
* and at the same time to be as minimal as it possible
* @type {number}
*/
const FACTORIAL_CACHE_SIZE = 1000;
/**
* We need to prepare factorial cache for a future usage
*/
let FACTORIAL_POINTS = [];
let FACTORIAL_CACHE = [];
/**
* Returns points in which we need to split factorial calculation
* to prevent a result to be greater than JS max number value
*
* @param max
* @returns {Array}
*/
function _getFactorialPoints(max) {
const points = [];
let point = 0;
let m = 2;
let end = false;
while (true) {
let f = 1;
while (f < Number.MAX_VALUE / m) {
f *= m;
m++;
if (m > max) {
end = true;
break;
}
}
if (end) {
break;
} else {
points[point] = m - 1;
point++;
}
}
return points;
}
/**
* Calculates factorial as an array of multipliers.
* Each number in array is max as possible to use in future calculations
*
* @param n
* @returns {[number]}
*/
function _calcFactorial(n) {
let point = 0;
let f = [1];
for (let i = 2; i <= n; ++i) {
if (i > FACTORIAL_POINTS[point]) {
point++;
f[point] = 1;
}
f[point] *= i;
}
return f;
}
/**
* Calculates probability of given value based on expected value
*
* @param expected
* @param exact
* @returns {number}
*/
function calcProbability(expected, exact) {
const bf = FACTORIAL_CACHE[exact];
const exactPart = Math.floor(exact / (bf.length + 1));
let h = 0;
let result = 1;
let step = 0;
while (exact > 0) {
h = Math.min(exact, exactPart);
result *= Math.pow(expected, h) / (bf[step] || 1);
step++;
exact -= h;
}
return Math.exp(-expected) * result;
}
/**
* Sets max size for factorial points storage object
*
* @param cacheSize
* @returns {calcProbability}
*/
calcProbability.setCacheSize = function(cacheSize) {
cacheSize = cacheSize || 1000;
FACTORIAL_POINTS = _getFactorialPoints(cacheSize);
FACTORIAL_CACHE.length = cacheSize;
for (let i = 0; i < FACTORIAL_CACHE_SIZE; ++i) {
FACTORIAL_CACHE[i] = _calcFactorial(i);
}
return calcProbability;
};
module.exports = calcProbability;