今回は冪等関数(一覧)。
「冪等 (idenpotent)」とは、1度写像を施すとその後何度その写像を施しても値が変わらない性質のこと*1。 数学っぽく書くと、任意の に対して が成り立つ関数 のことです。 射影 (projection) なんかがそういう性質を持ってます。 とか言っても、今回は別にこの性質がどうだこうだって話ではありません。 単なるカテゴリー分けの都合。
今回扱う関数は下表の通り:
メソッド | 返り値の型 | 説明 |
---|---|---|
sign(byte x) sign(short x) sign(int x) sign(long x) sign(float x) sign(double x) |
byte short int long float double |
符号関数 |
indicator(byte x) indicator(short x) indicator(int x) indicator(long x) indicator(float x) indicator(double x) |
byte short int long float double |
符号関数 (引数が0の場合のみ符号関数と値が異なる) |
round(float x, int scale) round(float x, int scale, int roundingMethod) round(double x, int scale) round(double x, int scale, int roundingMethod) |
float float double double |
四捨五入など |
sign(), indicator() は各プリミティブ型に対してオーバーロードされています。 引数の型と返り値の型は同じになっています。
符号関数 sign
まずは符号関数 (sign)。 定義はこんな感じ:読み方は「サイン」で sin と同じなので、数学では signum (シグナム)関数と書かれることもあるようです(wikipedia:符号関数)*2。 java.lang.Math では、こちらの名前で定義されています:
package java.lang; public final class Math{ ... public static float signum(float f){ ... } public static double signum(double d){ ... } }
サンプルコード。 値のアサーションと、java.lang.Math.signum() メソッドの挙動との比較をしてみます:
import static java.lang.Math.signum assert MathUtils.sign(2d) == 1d assert MathUtils.sign(0d) == 0d assert MathUtils.sign(-2d) == -1d // java.lang.Math.signum() メソッドと同じ挙動。 assert MathUtils.sign(2d) == signum(2d) assert MathUtils.sign(0d) == signum(0d) assert MathUtils.sign(-2d) == signum(-2d)
まぁ、問題なし。
indicator
次は indicator 関数。 この関数はほとんど符号関数と同じですが、x = 0 の時の値だけが異なります*3。サンプルコードはこんな感じ:
assert MathUtils.indicator(2d) == 1d assert MathUtils.indicator(0d) == 1d assert MathUtils.indicator(-2d) == -1d
値を丸める関数 round
最後は値の丸め(切り上げ・切り下げ・四捨五入など)を行う round 関数。 似たような関数は java.lang.Math にも定義されています:package java.lang; public final class Math{ ... public static double rint(double a) public static int round(float a) public static long round(double a) }
ただし、これらは値の丸め方が決め打ちにされているのと、round() はメソッドの戻り値の型が整数になっている点で、MathUtils#round() メソッドとは違います。 MathUtils#round() では関数としての引数以外に
- 丸めを行う桁の指定(第2引数)
- 値の丸め方(第3引数)
を指定する引数があります。
第2引数の「桁の指定」は、小数点から右に何桁目か?を指定する整数で行います:
assert MathUtils.round(123.456d, 0) == 123.0d assert MathUtils.round(123.456d, 1) == 123.5d assert MathUtils.round(123.456d, 2) == 123.46d assert MathUtils.round(123.456d, -1) == 120d
負の整数を渡してもきちんと動作します。 少し注意が必要なのは、指定した数字は小数第何位の数字ではないと言うところでしょうか。 第2引数に n を渡すと、小数第(n+1)位で値の丸めが行われます。
第3引数の「丸め方の指定」は BigDecimal の static フィールド(int 型の)で行います。 丸めの種類はざっとこんなのがあります:
ROUND_CEILING | 大きい値(+∞の方へ)切り上げる。 |
ROUND_FLOOR | 小さい値(-∞の方へ)切り下げる。 |
ROUND_UP | 0から遠ざかる方へ丸める(正の数の場合は切り上げ、負の数の場合は切り下げ)。 |
ROUND_DOWN | 0に近づく方へ丸める(正の数の場合は切り下げ、負の数の場合は切り上げ)。 |
ROUND_HALF_UP | (第2引数が0の場合)最も近い整数へ丸める。 2つの整数への距離が等しければ大きい方に丸める。 |
ROUND_HALF_DOWN | (第2引数が0の場合)最も近い整数へ丸める。 2つの整数への距離が等しければ小さい方に丸める。 |
ROUND_HALF_EVEN | (第2引数が0の場合)最も近い整数へ丸める。 2つの整数への距離が等しければ偶数に丸める。 |
ROUND_UNNECESSARY | 厳密な値が必要なときに指定。 丸めを行おうとすると ArithmeticException が投げられる |
ROUND_HALF_XXX は第2引数が0として説明してますが、0でなくても使えると思います(試してないけど)。 Java SE 5 から導入された列挙型 java.math.RoundingMode は使えないようです。
まぁ、こんな感じで。 そういえば冪零性って性質は全く使ってませんが・・・気にしないことにしとこう。
- 作者: 奥村晴彦,杉浦方紀,津留和生,首藤一幸,土村展之
- 出版社/メーカー: 技術評論社
- 発売日: 2003/05
- メディア: 単行本
- 購入: 2人 クリック: 61回
- この商品を含むブログ (61件) を見る
*1:余談ですが、2度(以上)施すと必ず0になる「冪零 (nilpotent)」なんて性質もあります。
*2:他にも「sgn(x)」と書かれることも。
*3:単位ステップ関数(wikipedia:単位ステップ関数) を使って と表すことができます。