# 正接(近似) Tangent Approximation # 引数 値 ($x) # 戻り値 正接(ラジアン) ($TangentApproximation) sub TANGENT{ my ($x) = @_; my $TangentApproximation = 0; my $Tangent = 0; my $PrevTangent = 0; my $X = abs($x); my $ZigZagNumber = 1; my @ZigZag = (0, 1); my $PrevZigZag = 0; my $Temp = 0; my $Factorial = 1; my $PowerX = 0; my $Pi = atan2(1, 1) * 4; my $Pi2 = $Pi / 2; my $Limit = 100; my $Epsilon = 1.0e-20; if(($x < -$Pi2) || ($Pi2 < $x)){ if((int($X / $Pi2) % 2) == 0){ # 90度未満 $X = ($X - (int($X / $Pi2) * $Pi2)); }else { # 90度以上 $X = ($X - (int($X / $Pi2) * $Pi2)) - $Pi2; } } for(my $i = 0; $i < $Limit; $i++){ # 累乗 $PowerX = $X ** ((2 * $i) + 1); if($i != 0){ # 分子 ジグザグ数 for(my $j = (2 * $i); $j <= (2 * $i) + 1; $j++){ $PrevZigZag = 0; # 最後尾 $ZigZag[$j] = 0; if(($j % 2) == 1){ # 奇数 タンジェント数 Zag Number for(my $k = 0; $k <= $j; $k++){ $Temp = $ZigZag[$k] + $PrevZigZag; # オイラー数で使用 $ZigZag[$k] = $PrevZigZag; # 次回使用する値 $PrevZigZag = $Temp; } }else { # 遇数 オイラー数 Zig Number for(my $k = $j - 1; $k >= 0; $k--){ $Temp = $ZigZag[$k] + $PrevZigZag; # タンジェント数で使用 $ZigZag[$k] = $Temp; # 次回使用する値 $PrevZigZag = $Temp; } } # ジグザグ数 ZigZag Number $ZigZagNumber = $Temp; } # 分母 階乗 for(my $j = (2 * $i) + 1; $j > ((2 * ($i - 1)) + 1); $j--){ $Factorial = $Factorial * $j; } } # 一つ前 $PrevTangent = $Tangent; # 正接(近似) Tangent $Tangent += ($ZigZagNumber / $Factorial) * $PowerX; # 収束判定 last if(abs($Tangent - $PrevTangent) < $Epsilon); } # 0度未満 $Tangent = -$Tangent if($x < 0); # 正接(近似) Tangent $TangentApproximation = $Tangent; return $TangentApproximation; }