絶対値を得るには,用意されている関数だけを用いて,
sqrt(x^2)
などとすることもできなくはないですが,こんなことは普通やりません。
awk で絶対値を与える関数は標準では用意されていません。絶対値を求めるには,次のような関数を作ります。
# x の絶対値を求める
# 使用例: x = abs(-10.95)
function abs(x)
{
return (x < 0) ? -x : x
}
平方根を求める関数はあります(sqrt)。もしないとしたらどのような関数を作りますか?
二数の小さい方
二数の大きい方
引数の符号により-1,0,1を返す
四捨五入
ある数を超えない最大の整数値
ある数より大きい最小の整数値
タンジェント
アークコサイン
アークサイン
アークタンジェント(1)
アークタンジェント(2)
平方根
ベータ関数
ガンマ関数
階乗(1)
階乗(2)
組合せの数(1)
組合せの数(2)
ポアソン分布の確率
二項分布の確率
カイ二乗分布の確率
半角数字を全角数字に変換
半角アスキー文字を全角アスキー文字に変換
年月日からユリウス日
ユリウス日を年月日に変換
ユリウス日から年
ユリウス日から月
ユリウス日から日
ユリウス日から曜日
ある年が閏年かどうかを判定する
# x, y の小さい方を求める
# 使用例: x = min(10, 5)
function min(x, y)
{
return (x < y) ? x : y
}
関数目次へ戻る
# x, y の大きい方を求める
# 使用例: x = max(10, 5)
function max(x, y)
{
return (x > y) ? x : y
}
関数目次へ戻る
# x > 0 のとき 1
# x = 0 のとき 0
# x < 0 のとき -1 を返す
# 使用例: y = sign(z)
function sign(x)
{
return (x > 0) ? 1 : (x == 0) ? 0 : -1
# 上の1行は以下と同じことを表す
# if (x > 0) {
# return 1
# }
# else if (x == 0) {
# return 0
# }
# else {
# return -1;
# }
}
関数目次へ戻る
# x を四捨五入した値を返す
# 使用例: y = round(z)
function round(x)
{
return (x > 0) ? int(x+0.5) : int(x-0.5)
}
関数目次へ戻る int,round,floor,ceil の違い
# x を超えない最大の整数値を返す
# 使用例: y = floor(x)
function floor(x)
{
return (x > 0) ? int(x) : (int(x) == x) ? x : int(x)-1
# 上の1行は以下と同じことを表す
# if (x > 0) {
# return int(x)
# }
# else if (int(x) == x) {
# return x
# }
# else {
# return int(x)-1
# }
}
関数目次へ戻る int,round,floor,ceil の違い
# x より大きい最小の整数値を返す
# 使用例: y = ceil(z)
function ceil(x)
{
return (int(x) == x) ? x : (x > 0) ? int(x)+1 : int(x)
# 上の1行は以下と同じことを表す
# if (int(x) == x) {
# return x
# }
# else if (x > 0) {
# return int(x)+1
# }
# else {
# return int(x)
# }
}
関数目次へ戻る int,round,floor,ceil の違い
# x の tangent を求める
# 使用例: y = tan(z)
function tan(x)
{
return sin(x)/cos(x)
}
関数目次へ戻る
# 1 ≧ x ≧ 0 の arc_cosine を求める
# 使用例: y = arc_cosine(z)
# 必要とする関数: arc_sine
function arc_cosine(x)
{
return arc_sine(sqrt(1-x^2))
}
関数目次へ戻る
# 1 ≧ x ≧ 0 の arc_sine を求める
# 使用例: y = arc_sine(z)
function arc_sine(x, a0, a1, a2)
{
if (x == 0) {
return 0
}
a0 = x*sqrt(1-x^2)
a1 = x
for (;;) {
a2 = a1*sqrt(2*a1/(a1+a0))
if (abs(a2-a1)/a1 < 1e-14) {
return a2
}
a0 = a1
a1 = a2
}
}
関数目次へ戻る
# x の arctangent を求める
# 使用例: y = arc_tangent(z)
function arc_tangent(x, a, b, a2, b2)
{
a = 1/sqrt(1+x^2)
b = 1
for (;;) {
a2 = (a+b)/2
b2 = sqrt(a2*b)
if (abs(a2 - b2)/b2 < 1e-14) {
return x/sqrt(a2*b2*(1+x^2))
}
a = a2
b = b2
}
}
関数目次へ戻る
# x の arctangent を求める
# 使用例: y = atan(z)
function atan(x)
{
return atan2(x, 1)
}
関数目次へ戻る
# 平方根を求める関数 sqrt2.awk
#
function sqrt2(x, x1, x2) {
if (x < 0) exit(1)
if (x == 0) return 0
x1 = 1
for (;;) {
x2 = (x1+x/x1)/2
if (abs(x2-x1)/x2 < 1e-10) {
return x2
}
x1 = x2
}
}
関数目次へ戻る
# ベータ関数
# 値が求められないときには,"Inf" という文字列を返すことに注意
function beta(x, y, z1, z2, z3)
{
z1 = gamma(x)
z2 = gamma(y)
z3 = gamma(x+y)
return (z1 == "Inf" || z2 == "Inf" || z3 == "Inf") ? "Inf" : z1/z3*z2
}
関数目次へ戻る
# ガンマ関数
# 必要とする関数 abs
# 値が求められないときには,"Inf" という文字列を返すことに注意
function gamma(x, a, b, z, factor, i, m, mg)
{
if (x > 171.6) {
printf "gamma: Overflow.\n" > "/dev/stderr"
return "Inf"
}
if (x <= 1.5) {
if (x >= 0.5) {
a = x-1.0
factor = 1.0
}
else {
m = int(x)
a = x-m
if (a == 0) {
printf "gamma: Invalid argument.\n" > "/dev/stderr"
return "Inf"
}
if (a >= -0.5) {
mg = abs(m)+1
}
else {
mg = abs(m)+2
a++
}
z = 1.0
for (i = 0; i < mg; i++) {
z *= x
x++
}
factor = 1.0/z
}
}
else {
m = int(x)
a = x-m
if (a <= 0.5) {
mg = m-1
}
else {
mg = m
a--
}
z = 1.0
for (i = 0; i < mg; i++) {
z *= (x-1.0)
x--
}
factor = z
}
b = ((((((((-0.42202e-11*a +0.120028e-10)*a +0.923397e-10)*a -0.12736143e-8)*a +0.62756218e-8)*a -0.1595268e-9)*a-0.2054743152e-6)*a +0.13385015466e-5)*a -0.25889950224e-5)*a
b = ((((((((((b -0.175458597517e-4)*a +0.1455961421399e-3)*a -0.3608378162548e-3)*a -0.80432977560424699e-3)*a +0.80232730222673465e-2)*a -0.1764524455014432e-1)*a -0.24552490005400017e-1)*a +0.19109110138769151)*a -0.23309373642178674)*a -0.42278433509846714)*a +1.0
return factor/(1.0+a)/b
}
関数目次へ戻る
# 整数値 n(n ≧ 0 )の階乗 n! を求める
# 使用例: x = factorial(10)
function factorial(n, retv, i)
{
retv = 1
for (i = 1; i <= n; i++) {
retv *= i
}
return retv
}
関数目次へ戻る
# 整数値 n(n ≧ 0 )の階乗 n! を求める(再帰関数)
# 使用例: x = factorial2(10)
function factorial2(n)
{
if (n == 0) {
return 1
}
else {
return n*factorial2(n-1)
}
}
関数目次へ戻る
# n から m (n ≧ m ≧ 0 )を取り出す組合せを求める
# 使用例: x = combination(10, 5)
function combination(n, m, i, c)
{
c = 1
k = min(n, n-m)
for (i = 1; i <= k; i++) {
c *= (n-i+1)/i
}
return c
}
関数目次へ戻る
# 組合せ(なるべく正確に求める)
function combination2(n, m, numerator, denominator, p, pivot, i, j, k, comb)
{
comb = 1.0
p = min(m, n-m)
if (p > 0) {
for (i = 1; i <= p; i++) {
numerator[i] = n-p+i
denominator[i] = i
}
for (k = 2; k <= p; k++) {
pivot = denominator[k]
if (pivot > 1) {
j = -((n-p)%k)
for (i = k; i <=p; i +=k) {
numerator[i+j] /= pivot
denominator[i] /= pivot
}
}
}
for (i = 1; i <= p; i++) {
if (numerator[i] > 1) {
comb *= numerator[i]
}
}
}
return comb
}
関数目次へ戻る
# ポアソン定数 lambda のポアソン分布の確率 f(lambda, x) を求める
# 使用例: y = Poisson(lambda, x)
function Poisson(lambda, x)
{
return exp(-lambda)*lambda^x/factorial(x)
}
関数目次へ戻る
# 母比率 p の二項分布の確率 f(p, n, x) を求める
# n は試行回数,x は対象事象の観察回数
# 使用例: y = Binomial(p, n, x)
# 必要とする関数: combination
function Binomial(p, n, x)
{
return combination(n, x) * p^x * (1-p)^(n-x)
}
関数目次へ戻る
# 自由度 df のカイ二乗分布において確率密度 f(x) を求める
# 使用例: chi_dist(2.34, 2)
function chi_dist(x, df)
{
return x^(df/2.0-1.0) * exp(-x/2) / 2^(df/2.0) / gamma(df/2.0)
}
関数目次へ戻る
# 0 〜 9 の数字の列の各文字を,0〜9に置き換える
# 使用例: i2zen("0123456789012")
# i2zen(12345)
function i2zen(num, i, retv)
{
for (i = 1; i <= length(num); i++) {
retv = retv substr("0123456789", substr(num, i, 1)*2+1, 2)
}
return retv
}
関数目次へ戻る
# いわゆるアスキー半角文字列の各文字を,いわゆる全角文字に置き換える
# 使用例: a2zen("01234ABCxyz#@")
function a2zen(str, i, retv)
{
for (i = 1; i <= length(str); i++) {
retv = retv substr(" !”#$%&’()*+,−./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_‘abcdefghijklmnopqrstuvwxyz{|}〜",
index(" !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",
substr(str, i, 1))*2-1, 2)
}
return retv
}
関数目次へ戻る
# 西暦年月日からユリウス日を得る
# y 年 m 月 d 日
function J_day(y, m, d)
{
return d-32075+int( 1461*(y+4800+ int( (m-14)/12) )/4 ) \
+int( 367*(m-2-int( (m-14)/12 )*12)/12 ) \
-int( 3*( int( (y+4900+int( (m-14)/12 ))/100 ) )/4 )
}
関数目次へ戻る
# ユリウス日 jul から西暦年を取り出す
function year(jul)
{
return substr(date(jul), 1, 4)
}
関数目次へ戻る
# ユリウス日 jul から月を取り出す
function month(jul)
{
return substr(date(jul), 6, 2)+0
}
関数目次へ戻る
# ユリウス日 jul から日を取り出す
function day(jul)
{
return substr(date(jul), 9, 2)+0
}
関数目次へ戻る
# 指定された西暦年月日の曜日を求める
# 引数
# y 西暦年(4桁)
# m 月
# d 日
# i 戻り値の種類指定
# 戻り値
# i が 1 のとき y年 m月 d日の 曜日を表す漢字1文字
# i が 1 以外のとき y年 m月 d日の 曜日を表す英字3文字
# 必要とする関数: J_day
function week(y, m, d, i)
{
return (i == 1) ? substr("日月火水木金土", ((J_day(y, m, d)+1)%7)*2+1, 2) \
: substr("SunMonTueWedThuFriSat", ((J_day(y, m, d)+1)%7)*3+1, 3)
}
関数目次へ戻る
# ユリウス日から西暦年月日を得る
function date(jul, l, n, iy, jm, kd)
{
l = jul+68569
n = int(4*l/146097)
l -= int((146097*n+3)/4)
iy = int(4000*(l+1)/1461001)
l -= int(1461*iy/4)-31
jm = int(80*l/2447)
kd = l-int(2447*jm/80)
l = int(jm/11)
jm = jm+2-12*l
iy = 100*(n-49)+iy+l
return sprintf("%4d/%02d/%02d", iy, jm, kd)
}
関数目次へ戻る
# 西暦年 y を与えてその年が閏年かどうかを判定する
function uruudosi(y)
{
return (month(J_day(y, 2, 29)) == 2) ? 1 : 0
}
関数目次へ戻る