私はスタートアップにPowerShellを登録しており、いつでも使えるようにしています。
最近では電卓として使用することが多いです。
四則演算子以外にも下記のような.NET Frameworkの数学関数が使用できるので、重宝します。
定数 eを指定して、自然対数ベースを表します。 | |
PI | 定数 PI を指定して、円の直径に対する円周の割合を表します。 |
Abs | オーバーロード。 指定した数値の絶対値を返します。 |
Acos | コサインが指定数となる角度を返します。 |
Asin | サインが指定数となる角度を返します。 |
Atan | タンジェントが指定数となる角度を返します。 |
Atan2 | タンジェントが 2 つの指定された数の商である角度を返します。 |
BigMul | 2 つの 32 ビット数値の完全な積を生成します。 |
Ceiling | 指定された数以上の数のうち、最小の整数を返します。 |
Cos | 指定された角度のコサインを返します。 |
Cosh | 指定された角度のハイパーボリック コサインを返します。 |
DivRem | オーバーロード。 2 つの数値の商を返し、出力パラメータとして剰余を渡します。 |
Exp | 指定した値で e を累乗した値を返します。 |
Floor | 指定された数以下の数のうち、最大の整数を返します。 |
IEEERemainder | 指定した数を別の指定数で除算した結果の剰余を返します。 |
Log | オーバーロード。 指定した数の対数を返します。 |
Log10 | 指定した数の底 10 の対数を返します。 |
Max | オーバーロード。 指定された 2 つの数のうち、大きい方を返します。 |
Min | オーバーロード。 2 つの数のうち、小さい方を返します。 |
Pow | 指定の数値を指定した値で累乗した値を返します。 |
Round | オーバーロード。 指定した値に最も近い数値を返します。 |
Sign | オーバーロード。 数値の符号を示す値を返します。 |
Sin | 指定された角度のサインを返します。 |
Sinh | 指定された角度のハイパーボリック サインを返します。 |
Sqrt | 指定された数値の平方根を返します。 |
Tan | 指定された角度のタンジェントを返します。 |
Tanh | 指定された角度のハイパーボリック タンジェントを返します。 |
PowerShellを電卓として使用するメリットとして、
- 計算のために入力した式をかくにんできる
- 履歴機能を使用して、再計算できる & この機能を利用して一部だけを変えて再度計算も可能
- よく使う計算式はスクリプト化して再利用可能
などがあげられます。
短所は、Windowsに付属の電卓と違ってSinとかも「ボタン一発」ではなく一文字一文字入力しなければ行けないことでしょうか?
Mathクラスの使用方法ですが、
PS C:\Work> [Math]::Sqrt(4) 2 PS C:\Work> [Math]::Pow(2,5) 32
のように [Math]::メソッド と記述します。
ぜひ電卓としても使用してみてください。慣れると重宝すること間違いなしです。
コメント
‘[Math]::’が邪魔っ気なのでメソッドを関数にしようとしてType.InvokeMemberメソッドを利用したのですが
何故か関数の中で使おうとすると下記のようなエラーが出ます。
function Min {
[Math].InvokeMember( "Min", "InvokeMethod", $null, $nul, $args)
}
Min 1 9
Exception calling "InvokeMember" with "5" argument(s): "メソッド ‘System.Math.Min’ が見つかりません。"
At line:2 char:20
しかしプロンプトから直接呼ぶと成功します
$myargs = 1,9
[Math].InvokeMember( "Min", "InvokeMethod", $null, $nul, $myargs)
1
バグなんでしょうか・・・?
function Min {
$myargs = 1, 9
[Math].InvokeMember( "Min", "InvokeMethod", $null, $nul, $myargs)
}
上記のような関数を作成してプロンプトから呼び出すと "1"を返してきました。
ということは、関数内から[Math].InvokeMemberを呼び出すことは問題ないということがわかります。
おそらく[Math].InvokeMemberに渡した$argsが問題となっているのだと思います。
根本的な解決方法ではないのですが
function Min {
[Math]::Min($args[0], $args[1])
}
というのはだめでしょうか?
はい、関数内で別個に配列を作って渡すのは問題ないみたいです。
$args自体も確認するとちゃんと値を保持しているみたいなんですが、
function Min {
$myargs = $args
[Math].InvokeMember( "Min", "InvokeMethod", $null, $nul, $args)
}
これでも実行時にエラーが出てしまうので、Type.InvokeMemberメソッドに$argsの参照を渡すこと自体が問題みたいですね。
Math.Minメソッドを関数にするだけなら[Math]::Min($args[0], $args[1]) でも全然問題ないんですが、
Type.InvokeMemberメソッドなら$argsを各引数に分解してメソッドに渡してくれるので、
一括で変換する場合にスマートに書けるかなと。
「呼び出された時の$argsの要素の数だけ新しい変数を作り、その名前を文字列としてメソッド名と","で繋げ、
生成した文字列をInvoke-Expressionで評価する関数の定義」、を文字列としてInvoke-Expressionで評価する
というやり方でやってみたら書けたには書けましたが、頭がこんがらがりました。
ほとんど手段が目的と化してます(笑)
>Type.InvokeMemberメソッドなら$argsを各引数に分解してメソッドに渡してくれるので、
一括で変換する場合にスマートに書けるかなと。
確かにこれができればスマートになりますね
>Invoke-Expressionで評価するというやり方でやってみたら書けたには書けましたが、
差し支えなければ参考までにどうやったか教えていただけませんか?
こんなのでよければ・・・
関数を定義する際、その関数の中でもswitch文によって値が代入された際の$_の内容を参照する都合上
どうしても展開式入りのヒア文字列にしなくてはいけないので、すごくややこしいです
# 静的メソッドにしか対応していません
switch ([math].getmembers()) {
{ $_.MemberType -eq "Method" }
{
# 展開式$(…)入りの関数定義のヒア文字列変数$strに代入する
$str = @"
function $($_.Name)
{
[string] `$exp = "[$($_.ReflectedType)]::$($_.Name)("
# この部分が$strに代入される際は展開されて [System.Math]::Min のようになります
if ( `$args.Count -ne 0 ) {
for ( `$i=0; `$i -lt `$args.Count; `$i++ ) {
New-Variable -Name arg`$(`$i) -Value `$args[`$i]
`$exp += "$" + "arg" + "`$i"
if ( `$args.Count -eq 1 -or `$i -eq `$args.Count-1 ) { break }
# 引数が一つだけの場合と最後の引数の場合は後ろにカンマが入るとまずいのでbreak
`$exp += ", "
}
}
`$exp += ")"
# `$exp | out-host
# 式確認用
Invoke-Expression `$exp
}
"@
Invoke-Expression $str
}
{ $_.MemberType -eq "Field" } {} # 力尽きました
}
ありゃ、そのまま貼り付けたはずなのですが、ヒア文字列の開始引用符 @" の後ろにスペースが付いてしまってますね
これをそのままコピペして実行するとエラーになるので、気をつけてください
なるほどw
switch ([math].getmembers()) {
{ $_.MemberType -eq "Method" }
としているので、すべて(静的メソッド)について確認できるわけですね。
これは勉強になります。
力作ありがとうございました。