なみひらブログ

学んだことを日々記録する。~ since 2012/06/24 ~

MathクラスのnextDownメソッド

背景

以下の本に

Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング

Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング

doubleとfloatの両方のパラメータに対して定義されているnextDownメソッドは、与えられた数値よりも小さな次の浮動小数点数を返します。例えば、bよりも小さな数値を生成するはずであったけれど、たまたま正確にbとなってしまったとしたら、Math.nextDown(b)を返すことができます。(対応するMath.nextUpメソッドは、Java6から存在しています。)

と書いてあって、「次の浮動小数」の部分がよく分からなかったのでちょっと動作確認しました。

※ちなみにnextDownメソッドJavadocは以下の通りです。
http://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextDown-double-

Returns the floating-point value adjacent to d in the direction of negative infinity.

※adjacent = 「隣り合った、隣接した」

動作確認

  • テストコード
    @Test
    public void test_nextDown(){
        // prepare
        final double d = 1.0;

        // action
        final double result = Math.nextDown(d);

        // check
        System.out.println(result);
        System.out.println(Double.doubleToRawLongBits(d));
        System.out.println(Double.doubleToRawLongBits(result));
    }


  • 結果
0.9999999999999999
4607182418800017408
4607182418800017407


  • Math#nextDown(double d)のコード
    public static double nextDown(double d) {
        if (Double.isNaN(d) || d == Double.NEGATIVE_INFINITY)
            return d;
        else {
            if (d == 0.0)
                return -Double.MIN_VALUE;
            else
                return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
                                               ((d > 0.0d)?-1L:+1L));
        }
    }

まとめ

  • 「次」とはdouble/floatの1刻み幅でずらした値。
  • 浮動小数点数の刻み幅の表現方法として、Double.doubleToRawLongBits(d)でlong(doubleと同じ64ビット)にして +/-1 して表現できる。
  • 使いどころは「bよりも小さな数値を生成したい場合、かつたまたま同じ値も許させない場合」
    • 利用シーンがまだ思いついていない(;´Д`)
    • nextUp()のほうがまだ使いどころがありそう(;´Д`)

参考

Java 8: Exact arithmetic operations supported in Math class - How To Do In Java