【Java】Math.floor(), ceil(), round() 動作互換アルゴリズムを試す 
2014/12/26 Fri [edit]
「Math 関数は遅い」みたいなことがよく書かれているが、実際どうなのか調べてみたかったので、例によっていくつかのサンプルを拾って試してみた。
その前に、Math.floor(), ceil(), round() の大まかな動作を図解で確認。

負の値には注意。特に round() は図でないとわかりにくい。
■アルゴリズム1
振り分けのしきい値を含まないように値を加算して、整数部分を変え小数部分を切り捨てる。
(例)
1.0 + 0.999999… = 1.999999… → 1
1.1 + 0.999999… = 2.099999… → 2
-0.50 - 0.499999… = -0.999999… → 0
-0.51 - 0.499999… = -1.009999… → -1
//Math.floor() 互換1
public static final int floor(final double value) {
return (value >= 0) ? (int)value : (int)(value - 0.99999999999999d);
// > 0 でも結果は同じ(value=0 を意識してるだけ)
}
//Math.ceil() 互換1
public static final int ceil(final double value) {
return (value > 0) ? (int)(value + 0.99999999999999d) : (int)value;
}
//Math.round() 互換1
public static final int round(final double value) {
return (value + 0.5d > 0) ? (int)(value + 0.5d) : (int)(value - 0.49999999999999d);
}
■アルゴリズム2
1.0 の剰余を調べ、ちょうど以外のとき1を加算し、整数部分を変え小数部分を切り捨てる(round() の 場合は 0.5 で処理を振り分ける)。それぞれは正負で処理をわける。
//Math.floor() 互換2
public static final int floor(final double value) {
if (value % 1 == 0) {
return (int)value;
} else {
return (value < 0) ? (int)(value - 1) : (int)value;
}
}
//Math.ceil() 互換2
public static final int ceil(final double value) {
if (value % 1 == 0) {
return (int)value;
} else {
return (value < 0) ? (int)value : (int)(value + 1);
}
}
//Math.round() 互換2
public static final int round(final double value) {
if (value < 0) {
return (value % 1 < -0.5) ? (int)(value - 1) : (int)value;
} else {
return (value % 1 < 0.5) ? (int)value : (int)(value + 1);
}
}
Math、アルゴリズム1、アルゴリズム2を試してみると、Math はネイティブコードを使っているためか、実行環境で結構違うみたいだった。以下は実行速度比較結果。
[PC の場合] (Windows8.1 x64 Intel Core 2.90G)
Math ≒ アルゴリズム1 > アルゴリズム2
[スマホの場合] (Android2.2 API8)
アルゴリズム1 > アルゴリズム2 > Math
アルゴリズム2は演算を2回するからか、どうしてもアルゴリズム1よりは遅い。Math はどの環境でも精度が高く演算されるようにできているからか、CPU パワーに依存するっぽい。float 型で作ってみたりしたけど、実行速度は変わらない。スマホなら FPU(浮動小数点演算プロセッサ)の性能でも結構変わるかもしれない。計算精度を気にしないなら、アルゴリズム1を使うのもいいだろう。PC の場合は Math とアルゴリズム1はほとんど変わらなかった。実数演算は 32bit マシンと 64bit マシンでもかなり違うだろう。
Java は Android が流行ったおかげか、未だにバージョンアップが繰り返されているから、以前遅かったものも最新バージョンでは速くなってたりするんだよね。時々試してみるのもいいかも。
- 関連記事
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/157-7c12ef53
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |