Swiftを試してみた(簡単な分布関数)

昨日の続きで(チラシの裏のように)書いてみています。今日は二項分布と正規分布。あとは、累積分布関数の逆関数norminvbinoinv)に加えてt分布とF分布があると日常的な統計処理には使えそう。(たぶん仕事はSwiftでなくRでやると思うけど)

関数名はMatlabと合わせてあります。

// 円周率
let PI: Double = 3.141592653589793238462643383279

// 階乗(二項係数の計算で使うかと思って作ったら、けっきょく使わなかった)
func factorial(_ n: Int) -> Int {
  if n <= 0 {
    return 1
  } else {
    var prod = 1
    for i in 1...n {
      prod *= i
    }
    return prod
  }
}

// 二項係数/組み合わせの数(nCk)
func nchoosek(_ n: Int, _ k: Int) -> Int {
  var prod: Int = 1
  if k != 0 {
    for i in 0...(k-1) {
      prod *= (n-i)
    }
    for i in 1...k {
      prod /= i
    }
  }
  return prod
}

// 二項分布の確率密度関数
func binopdf(_ x: Int, _ n: Int, _ p: Double) -> Double {
  return Double(nchoosek(n, x)) * pow(p, Double(x)) * pow(1-p, Double(n-x))
}

// 二項分布の累積分布関数(もっと良い方法があると思う)
func binocdf(_ x: Int, _ n: Int, _ p: Double) -> Double {
  var res = 0.0
  for i in 0...x {
    res += binopdf(i, n, p)
  }
  return res
}

// 正規分布の確率密度関数
func normpdf(_ x: Double, mu: Double, s: Double) -> Double {
  return normpdf(x) * s + mu
}
func normpdf(_ x: Double) -> Double {
  return 1 / sqrt(2.0 * PI) * exp(-x*x/2.0)
}

// 正規分布の累積分布関数
func normcdf(_ x: Double, _ mu: Double, _ s: Double) -> Double {
  return (1 + erf(x/sqrt(2))) / 2
}
func normcdf(_ x: Double) -> Double {
  return normcdf(x, 0, 1)
}