Day 4: Normal Distribution #1

Sort by

recency

|

28 Discussions

|

  • + 0 comments

    Based on the solutions of the past:

    # X ~ N(30, 4**2)
    mu,sig = 30,4
    INF = float('inf')
    cases = [(-INF, 40), (21,INF), (30,35)]
    def p(f: float): print(f'{f:.3f}')
    `
    
    `
    ### Method 1: bruteforce approx
    import random
    def sample(): return random.gauss(mu,sig)
    # you can also sample randomly by taking 2 outputs of random.random() && using the Box-Muller formula.
    # if `random` itself is banned, you can try making a simple LCG from scratch, but it may be too biased.
    def brute(a, b, tries: int=99999):
      return sum(a<sample()<b for _ in range(tries)) / tries
    
    for args in cases: p(brute(*args))
    `
    
    `
    ### Method 2: \Phi(z) = (1+erf(z/\sqrt{2}))/2
    import math
    def cdf_N(z: float): return (1 + math.erf(z/math.sqrt(2))) / 2
    def cdf_X(z: float): return cdf_N((z-mu)/sig)
    
    p(cdf_X(40))
    p(1-cdf_X(21))
    p(cdf_X(35)-cdf_X(30))
    `
    
    `
    ### Method 3: Riemann summation
    # pdf(t) = \frac{e^{-t^2/2}}{\sqrt{2\pi}}
    def pdf(t: float): return math.exp(-t*t/2) / math.sqrt(2*math.pi)
    def phi(t): # approximate the CDF
        t_abs = abs(t)
        delta, eps = 1e-3, 1e-6
        s = 0
        while (d:=delta*pdf(t_abs)) >= eps:
          s += d
          t_abs += delta
        return s if t <= 0 else 1-s # \Phi(t) = 1-\Phi(t) if t > 0
    def cdf(z): return phi((z-mu)/sig)
    p(cdf(40))
    p(1-cdf(21))
    p(cdf(35)-cdf(30)
    
  • + 0 comments

    Can I use random package instead?

    import random
    
    mu = 30
    sigma = 4
    n = 1_000_000
    
    a = [random.gauss(mu, sigma)<40 for i in range(n)]
    a = round(sum(a)/n, 3)
    
    b = [random.gauss(mu, sigma)>21 for i in range(n)]
    b = round(sum(b)/n, 3)
    
    
    c = [30 < random.gauss(mu, sigma) < 35 for i in range(n)]
    c = round(sum(c)/n, 3) 
    
    print(a)
    print(b)
    print(c)
    
  • + 0 comments

    So everyone publishes his code??
    Now here is mine (wasn't aware of , what a pity).

    import math
    # ouch, no scipy 
    
    density = lambda t: math.exp(-t*t/2) / math.sqrt(2*math.pi) 
    # note acuracy of math.pi 8 digits: maybe better define own
    
    def phi(t):
        tabs = abs(t)
        delta, eps = 0.001, 1e-6
        s = 0
        while ...:
            d = delta * density(tabs)
            s += d
            tabs += delta
            if d < eps: break
        return s if t <= 0 else 1-s
    
    normalize = lambda mu, sigma: lambda t: (t-mu) / sigma
    
    # main
    
    n = normalize(30, 4)
    
    print(phi(n(40)))
    print(1-phi(n(21)))
    print(phi(n(35)) - phi(n(30)))
        
    
  • + 0 comments

    Here is my answer:

    # Enter your code here. Read input from STDIN. Print output to STDOUT
    import math
    def get_function(x):
        mu = 30
        sig = 4
        gaussian_func = (1 / (sig * math.sqrt(2 * math.pi))) * math.exp(-((x - mu) ** 2) / (2 * sig ** 2))
        return gaussian_func
    
    start_value = 10
    end_value = 50
    step = 0.0001
    
    x = [start_value + i * step for i in range(int((end_value - start_value) / step) + 1)]
    y0 = 0
    y1 = 0
    y2 = 0
    y3 = 0
    
    for i in range(len(x)):
        y0 += get_function(x[i]) * step
        if x[i] < 40:
            y1 += get_function(x[i]) * step
    
        if x[i] > 21:
            y2 += get_function(x[i]) * step
    
        if 30 < x[i] < 35:
            y3 += get_function(x[i]) * step
    
    result1 = int((y1 / y0) * 1000) / 1000
    result2 = int((y2 / y0) * 1000) / 1000
    result3 = int((y3 / y0) * 1000) / 1000
    
    print(str(result1))
    print(str(result2))
    print(str(result3))
    
  • + 0 comments

    erf and erfc, which are +- antiderivatives of the gaussian (with a specific choice of +c) is in the python math library. So, you can easily write the CDF of normal dist using either erf or erfc.

    import math
    
    mu = 30
    sig = 4
    def cdf(x):
        return math.erfc((mu-x)/(sig*math.sqrt(2)))/2
    print(cdf(40))
    print(1 - cdf(21))
    print(cdf(35)-cdf(30))