- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
# https://www.source-code.biz/snippets/vbasic/9.htm
def calc_probability_of_inverse_normal_cumulative_distribution(probability)
raise Math::DomainError unless probability.instance_of? BigDecimal
a1 = -39.6968302866538
a2 = 220.946098424521
a3 = -275.928510446969
a4 = 138.357751867269
a5 = -30.6647980661472
a6 = 2.50662827745924
b1 = -54.4760987982241
b2 = 161.585836858041
b3 = -155.698979859887
b4 = 66.8013118877197
b5 = -13.2806815528857
c1 = -7.78489400243029E-03
c2 = -0.322396458041136
c3 = -2.40075827716184
c4 = -2.54973253934373
c5 = 4.37466414146497
c6 = 2.93816398269878
d1 = 7.78469570904146E-03
d2 = 0.32246712907004
d3 = 2.445134137143
d4 = 3.75440866190742
probability_low = 0.02425
probability_high = 1 - probability_low
raise Math::DomainError if probability <= 0 || probability >= 1
# glhf to the person who's gonna refactor this
# rubocop:disable Layout/LineLength
if probability < probability_low
q = (-2 * Math.log(probability))**0.5
(((((((((((c1 * q) + c2) * q) + c3) * q) + c4) * q) + c5) * q) + c6) / ((((((((d1 * q) + d2) * q) + d3) * q) + d4) * q) + 1)).to_f
elsif probability <= probability_high
q = probability - 0.5
r = q * q
(((((((((((a1 * r) + a2) * r) + a3) * r) + a4) * r) + a5) * r) + a6) * q / ((((((((((b1 * r) + b2) * r) + b3) * r) + b4) * r) + b5) * r) + 1)).to_f
else
q = (-2 * Math.log(1 - probability))**0.5
(-((((((((((c1 * q) + c2) * q) + c3) * q) + c4) * q) + c5) * q) + c6) / ((((((((d1 * q) + d2) * q) + d3) * q) + d4) * q) + 1)).to_f
end
# rubocop:enable Layout/LineLength
end