ジャバ:Double.MIN_NORMAL を double に追加しても数値は変わりません
-
21-12-2019 - |
質問
MIN_NORMAL は、「通常の」double に加算できる値であり、数値が変化すると考えていました。例えば。Double.MIN_NORMAL を 0.1d に追加すると、0.1d とは異なる値が得られますが、私の理解は間違っています。
public static void test(double val) {
if (val == (val - Double.MIN_NORMAL*1e50d))
System.out.printf("val == (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
else
System.out.printf("val != (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
}
これにより、以下が生成されます。
test(0.0d);
> val != (val - Double.MIN_NORMAL*1e50d) for val=0.00000000000000000000
test(1.0d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=1.00000000000000000000
test(0.1d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=0.10000000000000000000
誰か、ここで私の論理に反することを説明してください。MIN_NORMAL に 1e50d を掛けても同じ数値が得られるということです。
バイナリ表現を確認したところ、1 * Double.MIN_NORMAL は 2 * Double.MIN_NORMAL とは異なりますが、これらをゼロ以外から減算しても元の数値は変わりません。
解決
MIN_NORMAL
Javadoc に記載されているように、これは正規化された最小値のみです double
価値。しかし、それは次のようなものであるという意味ではありません 1
のために int
s:浮動小数点値の場合は、次のようになります。 いいえ 次の表現可能な値に変更するために追加できる標準の「eps」。「eps」は常に、指定された浮動小数点値の指数に依存します。それが彼らが呼ばれる理由です フローティング 最後にポイント:)
ただし、Java 1.6 以降では、 Math.nextAfter()
与えられた場合に返されるもの double
, 、次または前の表現可能 double
.
古い Java バージョンでは、いつでもいじることができます Double.doubleToLongBits()
, 、その結果をインクリメントまたはデクリメントし、次のように逆変換します。 Double.longBitsToDouble()
;これにより、次または前の表現可能が得られます double
価値 - ほとんどの場合:いくつかの特殊なケース (NaN、無限値) があるため、浮動小数点の初心者にはお勧めできません:)
他のヒント
ダブルは限られた精度を持っています。min_normalは2e-1022です。それを追加しない限り、2E-1000のBallparkにも入らない限り落とされます。