はじめに
プログラミングの問題をパズル感覚で解くことがあるのですが、時折「小数点以下の値がある場合・・・」のような問題が出てくることがあるんですね。
その際、doubleの値に小数点以下の値が含まれているかどうかの判断方法を、毎度毎度google検索で検索しては脳みそから捨てて、、、を繰り返しているので、そのループをなくすために記事化&サンプルコードの作成をしてみたものです。
注意
- doubleの値に小数点以下の値があるかどうか、の判定だけに注力しています。
- 有無だけしか見ないため、小数点以下の値の正しさはまったく考慮していません。
- 値の正しさを求めるのであれば、BigDecimalなどを使った解決法があるかと思います。
コード例
採用したコード
boolean変数に格納するために計算している箇所が、小数点以下の値の有無を判断するロジックになってます。
double d = 3.0 / 2.0; // d = 1.5
boolean b = d % 1 != 0; // b = true
流れは、
- d % 1
- 1で割った余りを取得します。小数点以下の値のみ抽出された結果が返ります。
- d % 1 != 0
- d % 1の結果と 0 を比較し、一致しなければtrue(=>小数点以下の値あり)となります。
サンプルコード
動作確認で使用したコードは以下となります。(利用する場合は、クラスなどは補完ください)
public static void main(String[] args) {
double d = 3.0 / 2.0; // = 1.5
System.out.println(hasAfterTheDecimalPoint(d));
}
private static boolean hasAfterTheDecimalPoint(double d) {
return d % 1 != 0;
}
ボツ案
ボツ1(動作しない)
小数点が結果に含まれていればいいなら、文字列に変えて”.”があるか調べればいいんじゃね?と考えて産み出されたコードがこちら。
double d = 3.0 / 2.0;
boolean hasDecimalPoint = String.valueOf(d).indexOf(".") != -1;
doubleの結果をprintlnすると分かるのですが、doubleを文字列変換すると、割り切れる数値であっても”.”が含まれます。
例:4.0 / 2.0 の結果をdoubleに代入 => 2.0
したがって、indexOf(“.”)の結果は必ず0以上の数値が返るため、常にtrue(小数点以下の値あり)となってしまいます。
ボツ2
文字列の解析に拘って産み出されたものが次のコードです。
double d = 3.0 / 2.0;
boolean hasAfterTheDecimalPoint = String.valueOf(d).matches("[\\d]+\\.0$") != -1;
このコードは、正規表現で”何らかの数字の繰り返し.0″終わりの値であるかをチェックするため、動作自体はします。
ただ、採用案に比べると簡単に書けてないですね。文字列への変換、正規表現の構文考案、正規表現のパターンコンパイルが都度発生するコードになっているので、無駄なコストもかかってしまいます。
(頻繁に使う正規表現であれば、事前にPattern.compile()することで、matchesのコストは少し下げられはします)
最後に
冒頭にも書きましたが、プログラミングの問題を解く際に使うケースがある程度ですが、それでも突然出てこられると戸惑うんですよね。「前も検索したな~」とか思いながら検索することもしばしば。
JavascriptだとNumber.isInteger()を使えば、今回の課題は一瞬でコード成立してしまうので、そういうのないかなぁとか調べてしまったり。
自作で考えるよ、となったときの一助になれば幸いです。
コメント