知っていて当たり前-07　さまざまな関数

# 知っていて当たり前-07　さまざまな関数

以下では，主にスカラーを引数とする例を示しているが，ドット記法により配列（ベクトル，行列）も引数にできるものもある。

## 1.　偶数か？　`iseven()`


```julia
iseven(8), iseven.([1, 2, 3, 4, 5])
```




    (true, Bool[0, 1, 0, 1, 0])



## 2.　奇数か？　`isodd()`


```julia
isodd(9)
```




    true



## 3.　2の累乗数か？　`ispow2()`


```julia
ispow2(128), ispow2(27362)
```




    (true, false)



## 4.　次の累乗数　`nextpow()`


```julia
nextpow(2, 1000), nextpow(12, 1000)
```




    (1024, 1728)



## 5.　前の累乗数　`prevpow()`


```julia
prevpow(2, 1000), prevpow(12, 1000)
```




    (512, 144)



## 6.　法による累乗　`powermod()`, `mod()`


```julia
powermod(2, 6, 5), mod(2^6, 5)
```




    (4, 4)



## 7.　平方根　`sqrt()`


```julia
sqrt(8), sqrt(-8 + 0im), sqrt(Complex(-8))
```




    (2.8284271247461903, 0.0 + 2.8284271247461903im, 0.0 + 2.8284271247461903im)



## 8.　整数平方根　`isqrt()`


```julia
isqrt(8), isqrt(9)
```




    (2, 3)



## 9.　三乗根　`cbrt()`, 　`^(1/3)`


```julia
cbrt(8), 8^(1/3), cbrt(-8)
```




    (2.0, 2.0, -2.0)




```julia
(-8.0)^(1/3)　# エラーになる
```


```julia
Complex(-8.0)^(1/3)
```




    1.0 + 1.7320508075688772im




```julia
x, y = 2, 3;
```


```julia
x∛y, x * ∛y
```




    (2.8844991406148166, 2.8844991406148166)



## 10.　階乗　n!

### 10.1.　`factorial()`


```julia
factorial(20), prod(1:20)
```




    (2432902008176640000, 2432902008176640000)




```julia
using SpecialFunctions
gamma(20), exp(lgamma(20))
```




    (1.21645100408832e17, 1.2164510040883208e17)




```julia
exp(logfactorial(10)), factorial(10)
```




    (3.6288000000000084e6, 3628800)




```julia
factorial(21) # OverflowError
```



```julia
factorial(big(21)), exp(logfactorial(21))
```




    (51090942171709440000, 5.109094217170978e19)



### 10.2.　対数Γ　`lgamma()`, `loggamma()`


```julia
lgamma(11), loggamma(11)
```




    (15.104412573075518, 15.104412573075518)




```julia
logabsgamma(11) # (log(abs(gamma(x))), sign(gamma(x)))
```




    (15.104412573075518, 1)



## 11.　組み合わせの数　nCi　`binomial()`


```julia
binomial(5, 3)
```




    10




```julia
factorial(5) ÷ (factorial(3) * factorial(5 - 3))
```




    10




```julia
div(factorial(5), factorial(3) * factorial(5 - 3))
```




    10




```julia
choose(n, i) = div(factorial(n), factorial(i) * factorial(n - i))
```




    choose (generic function with 1 method)




```julia
choose(5, 3)
```




    10



## 12.　最大公約数　`gcd()`


```julia
a = 97; b = 101; c = 37;
gcd(a*b, a*c)
```




    97



## 13.　最小公倍数　`lcm()`


```julia
a = 81; b = 6; c = 24;
lcm(a, c), lcm(a, b, c)
```




    (648, 648)



## 14.　符号　`sign()`


```julia
sign(10), sign(0), sign(-2)
```




    (1, 0, -1)



## 15.　絶対値　`abs()`


```julia
abs(-1), abs(-3.0)
```




    (1, 3.0)




```julia
abs(2 + 3im), sqrt(2^2 + 3^2)
```




    (3.605551275463989, 3.605551275463989)



## 16.　商と剰余　`divrem()`


```julia
divrem(14, 3), divrem(14, -3), divrem(-14, 3), divrem(-14, -3)
```




    ((4, 2), (-4, 2), (-4, -2), (4, -2))



## 17.　床　`floor()`, 　`fld()`, 　`div(..., RoundDown)`


```julia
floor(3.14)
```




    3.0




```julia
floor(Int, 3.14)
```




    3




```julia
fld(7.35, 2.8) # 7.35 / 2.8 = 2.625 => floor divide
```




    2.0




```julia
div(7.35, 2.8, RoundDown)
```




    2.0




```julia
div(7.35, 2.8)
```




    2.0




```julia
floor(Int, 7.35/2.8)
```




    2




```julia
floor(1.3), floor(-1.3)
```




    (1.0, -2.0)



## 18.　天井　`ceil()`, 　`cld()`, `div(..., RoundUp)`


```julia
ceil(3.14), ceil(Int, 3.14)
```




    (4.0, 4)




```julia
cld(5.5, 2.2) # 5.5/2.2 = 2.5 => ceil divide
```




    3.0




```julia
div(5.5, 2.2, RoundUp)
```




    3.0




```julia
div(5.5, 2.2)
```




    2.0




```julia
ceil(Int, 5.5/2.2)
```




    3




```julia
ceil(1.3), ceil(-1.3)
```




    (2.0, -1.0)



## 19.　丸め　`round()`


```julia
round(pi, digits=5)
```




    3.14159



いわゆる四捨五入とは異なる場合がある。


```julia
round(2.15, digits=1), round(2.25, digits=1)
```




    (2.2, 2.2)




```julia
round(pi), round(Int, 1pi)
```




    (3.0, 3)




```julia
round(Int, 1.3 + 2.2)
```




    4




```julia
round(1.3), round(-1.3)
```




    (1.0, -1.0)




```julia
round(1.6), round(-1.6)
```




    (2.0, -2.0)



## 20.　切り捨て　`trunc()`


```julia
trunc(1.3), trunc(-1.3)
```




    (1.0, -1.0)




```julia
trunc(1.6), trunc(-1.6)
```




    (1.0, -1.0)



## 21.　繰り返し　`repeat()`

`repeat(a, b)` は，「a を b 回繰り返す」ではあるが，a はスカラーではだめで，ベクトルでなくてはならない（たとえ要素数が 1 でも）。


```julia
repeat([1,2,3], 2)
```




    6-element Vector{Int64}:
     1
     2
     3
     1
     2
     3




```julia
repeat([999], 3)
```




    3-element Vector{Int64}:
     999
     999
     999



要素数が 1 個の文字列ベクトルを繰り返すのと，1個の文字列を繰り返すのでは結果は異なる。


```julia
repeat(["a"], 5)
```




    5-element Vector{String}:
     "a"
     "a"
     "a"
     "a"
     "a"




```julia
repeat(["abc"], 5)
```




    5-element Vector{String}:
     "abc"
     "abc"
     "abc"
     "abc"
     "abc"




```julia
repeat("a", 5)         # "aaaaa"
```




    "aaaaa"




```julia
repeat("abc", 3)
```




    "abcabcabc"



1 つの数値を繰り返すことで同じ要素を持つベクトル，配列を作ることができる。


```julia
repeat([0], 3)
```




    3-element Vector{Int64}:
     0
     0
     0




```julia
zeros(Int64, 3) # 専用の関数がある
```




    3-element Vector{Int64}:
     0
     0
     0




```julia
repeat([1.0], 3, 4)
```




    3×4 Matrix{Float64}:
     1.0  1.0  1.0  1.0
     1.0  1.0  1.0  1.0
     1.0  1.0  1.0  1.0




```julia
ones(Float64, 3, 4) # 専用の関数がある
```




    3×4 Matrix{Float64}:
     1.0  1.0  1.0  1.0
     1.0  1.0  1.0  1.0
     1.0  1.0  1.0  1.0




```julia
repeat([0], 1, 5) # 1 x 5 行列
```




    1×5 Matrix{Int64}:
     0  0  0  0  0




```julia
zeros(Int64, 1, 5) # 専用の関数がある
```




    1×5 Matrix{Int64}:
     0  0  0  0  0



## 22.　複雑な繰り返し


```julia
repeat([10 20 30], inner=(1,2))
```




    1×6 Matrix{Int64}:
     10  10  20  20  30  30




```julia
repeat([10 20 30], inner=(1,2,1))
```




    1×6×1 Array{Int64, 3}:
    [:, :, 1] =
     10  10  20  20  30  30




```julia
repeat([10 20 30], inner=(1,2,3)) # 3 次元配列
```




    1×6×3 Array{Int64, 3}:
    [:, :, 1] =
     10  10  20  20  30  30
    
    [:, :, 2] =
     10  10  20  20  30  30
    
    [:, :, 3] =
     10  10  20  20  30  30




```julia
a = [1 2 3]             # 1 2 3 すなわち 1 x 3 配列
```




    1×3 Matrix{Int64}:
     1  2  3




```julia
repeat(a)               # 1 2 3 すなわち 1 x 3 配列
```




    1×3 Matrix{Int64}:
     1  2  3




```julia
repeat(a, outer=1)      # 1 2 3 すなわち 1 x 3 配列
```




    1×3 Matrix{Int64}:
     1  2  3




```julia
repeat(a, outer=2)
```




    2×3 Matrix{Int64}:
     1  2  3
     1  2  3




```julia
repeat(a, outer=3)
```




    3×3 Matrix{Int64}:
     1  2  3
     1  2  3
     1  2  3




```julia
repeatn(x::Int64, y::Int64) = reshape((1:x) .* ones(Int64, y)', x * y)
repeach(x::Int64, y::Int64) = reshape(ones(Int64, y) .* (1:x)', x * y)　# '
```




    repeach (generic function with 1 method)




```julia
repeat("ha", 3) # "hahaha"
```




    "hahaha"



## 23.　ランレングス・エンコーディング run length encoding　`rle()`

同じ数，文字，文字列が何個続くか勘定する


```julia
using StatsBase
rle([1, 1, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1])
```




    ([1, 2, 3, 2, 1], [2, 1, 3, 4, 5])




```julia
rle(['a', 'a', 'b', 'b', 'b', 'a'])
```




    (['a', 'b', 'a'], [2, 3, 1])




```julia
rle(["foo", "bar", "foo", "foo"])
```




    (["foo", "bar", "foo"], [1, 1, 2])



## 24.　ランダム（乱数関連）


```julia
using Random # 乱数関連の関数を使うときに必要
```


```julia
Random.seed!(123); # デバッグ時など，同じ乱数列を発生させる必要があるときに指定する。数は何でもよい。
```

### 24.1.　一様乱数配列　`rand()`


```julia
rand(3) # rand(Float64, 3) がデフォルト
```




    3-element Vector{Float64}:
     0.521213795535383
     0.5868067574533484
     0.8908786980927811



`rand()` の第 1 引数には様々なものが指定できる。


```julia
rand(Int8, 3) # 型の指定
```




    3-element Vector{Int8}:
     -97
     -42
      40




```julia
rand(Int32, 3)
```




    3-element Vector{Int32}:
      1761969234
     -2037264516
       767353613




```julia
using Distributions
Z = rand(Uniform(-10, 10), 5) # 分布関数のオブジェクト
```




    5-element Vector{Float64}:
     -9.103639899650178
      8.667065745543301
      1.6111996374908237
     -3.455242414874329
      0.5399183759397292




```julia
rand(1:6, 10) # 具体的なベクトル
```




    10-element Vector{Int64}:
     6
     1
     3
     3
     1
     5
     4
     4
     2
     2




```julia
rand(["a", "b", "c", "d"], 5)
```




    5-element Vector{String}:
     "d"
     "d"
     "a"
     "b"
     "a"




```julia
rand(('x', 'y', :z), 5)
```




    5-element Vector{Any}:
     'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
     'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
     'y': ASCII/Unicode U+0079 (category Ll: Letter, lowercase)
     :z
     'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)




```julia
rand(2, 3) # 次元の指定で配列を生成する
```




    2×3 Matrix{Float64}:
     0.0905512  0.311448  0.20453
     0.581912   0.121148  0.38669



### 24.2.　Bool 乱数　`bitrand()`


```julia
bitrand(3, 5)
```




    3×5 BitMatrix:
     1  0  1  0  0
     0  1  1  1  0
     0  1  1  0  1




```julia

```

### 24.3.　標準正規乱数配列　`randn()`


```julia
randn(5)
```




    5-element Vector{Float64}:
      0.1707967032029406
     -1.7171200973796241
      1.1067814366003583
      1.1486968319829451
      0.615739830679831




```julia
randn(2, 3)
```




    2×3 Matrix{Float64}:
     -1.6516    1.54867  -1.74333
      0.21814  -1.94329   0.228246



### 24.4.　正規乱数配列　`rand(Normal(μ, σ), n`

Distributions パッケージにある `Normal(μ, σ)` からランダムサンプリングすればよい。


```julia
using Distributions
z = rand(Normal(50, 10), 10000);
```


```julia
using Statistics
mean(z), std(z)
```




    (50.0338818915161, 10.147362996006324)



### 24.5.　多次元正規乱数配列　`rand(MvNormal(μ, Σ), n)`

Distributions パッケージにある `MvNormal(μ, Σ)` からランダムサンプリングすればよい。


```julia
using Distributions
μ = [0, 0, 0];
Σ = [1.0 0.5 0.6
     0.5 1.0 0.7
     0.6 0.7 1.0];
x = rand(MvNormal(μ, Σ), 2000);
```

できる行列のサイズに注意（結果を転地しておくと後々便利かも）。


```julia
size(x)
```




    (3, 2000)




```julia
using Statistics
cor(x, dims=2)
```




    3×3 Matrix{Float64}:
     1.0       0.467286  0.576937
     0.467286  1.0       0.703519
     0.576937  0.703519  1.0



### 24.6.　無作為抽出（再掲） `rand()`


```julia
rand(1:6, 5) # min0:max0 から n 個を無作為抽出
```




    5-element Vector{Int64}:
     2
     2
     3
     4
     2




```julia
rand(["A", "B", "C"], 5) # ベクトル要素を無作為抽出
```




    5-element Vector{String}:
     "B"
     "A"
     "B"
     "A"
     "C"




```julia
rand(('x', 'y', :z), 5)  # ベクトル要素を無作為抽出
```




    5-element Vector{Any}:
     :z
     'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
     'y': ASCII/Unicode U+0079 (category Ll: Letter, lowercase)
     :z
     :z



### 24.7.　復元抽出と非復元抽出　`sample()`


```julia
sample(1:10, 5, replace=true)　# 復元抽出：同じものが抽出される可能性がある
```




    5-element Vector{Int64}:
     3
     4
     5
     1
     8




```julia
sample(1:10, 5, replace=false)　# 非復元抽出：同じものは抽出されない
```




    5-element Vector{Int64}:
      1
      2
      6
     10
      5




```julia
sample(1:10, 5, replace=true, ordered=true) # 抽出結果を並べ替える
```




    5-element Vector{Int64}:
     2
     2
     4
     6
     9



### 24.8.　シャッフル　`shuffle()`

非復元抽出で，母集団のサイズと同じ数だけ抽出することである。


```julia
a = shuffle(collect(1:10))  # 1 ~ 10 をシャッフルして返す
```




    10-element Vector{Int64}:
      5
      2
      4
      6
      1
      7
      3
      8
     10
      9




```julia
b = shuffle(["foo", "bar", "baz", "boo", "zoo"])
```




    5-element Vector{String}:
     "boo"
     "bar"
     "foo"
     "baz"
     "zoo"