Java7 のソースコードをぼーっと見ていたところ、数値の桁数と符号(プラスとマイナス)の判定を行っている箇所がありました。ここでは、それを紹介しています。
Javaのバージョンは多分です。Javaのことが嫌いなこともあり、ほとんど素人同然です。
スポンサーリンク
int 型と long 型の数値の桁数を求める
まずは、long 型の桁数を求める実装の紹介です。
/// x は正の数である必要がある static int stringSize(long x) { long p=10; for(int i=1; i<19; i++) { if(x < p) { return i; } p = 10 * p; } return 19; }
スッキリしているように思います。そして、次は int 型の桁数を求めている部分です。
final static int[] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; /// x は正の数である必要がある static int stringSize(int x) { for (int i=0;; i++) { if(x <=sizeTable[i]) { return i+1; } } }
ホワイ?????
sizeTable とか出てきています。なぜでしょうか? long 型の実装を真似れば次のように記述できるように思います。意地でも long 方は使いたくなかったように思えます。真相はわかりませんが。。。
static int stringSize(int x) { long p = 10; for(int i=1; i<10; i++) { if((long)x < p) { return i; } p = 10 * p; } return 10; }
数値の符号(プラス・マイナス・ゼロ)を判定する
続いて数値の符号を判定する実装部分の紹介です。はっきり言ってわかりづらいです。なお、int 型も long 型も同じ実装方法でした。
// int 型の符号を求める public static int signum(int i) { return ((i >> 31) | (-i >>> 31)) ; } // long 型の符号をもとめる public static int signum(long i) { return (int)((i >> 63) | (-i >>> 63)); }
上記の関数がどのように結果を返すのかをまとめたものが下表になります。int 型も long 型も結果は同じとなります。
引数 | (i >> 31) | (-i >>> 31) | リターン値 |
---|---|---|---|
正数 | 0 | 1 | 1 |
負数 | -1 | 0 | -1 |
ゼロ | 0 | 0 | 0 |
ビット演算において、>> は符号の情報を保持したままシフトし、>>> は符号の情報などお構いなしにシフトします。この違いを利用して符号情報を抽出しています。
また、負数の先頭ビットは 1 であり、正数の先頭ビットは 0 ということも覚えておいて損はないでしょう。