0

Javaでは、変数もfloatである場合、変数を否定することと、変数にfloatから1を引いた値を掛けることの間に違いはありますか?

4

4 に答える 4

2

Java は IEEE の 2 進浮動小数点表現を使用し、符号は別のビットで表されます。の乗算-1と符号の反転は、-xこの符号ビットを反転することによって行われますが、残りの表現は変更されません。-1.0f正確な表現があり、 の表現の精度を変更する可能性がないため、結果に違いがないのはそのためですx

于 2016-04-25T12:51:25.190 に答える
2

JLS §15.15.4「単項マイナス演算子 -」では、

浮動小数点値の場合、x が +0.0 の場合、0.0-x は +0.0 ですが、-x は -0.0 であるため、否定はゼロからの減算と同じではありません。単項マイナスは、浮動小数点数の符号を反転するだけです。関心のある特別なケース:

オペランドが NaN の場合、結果は NaN になります。(NaN には符号がないことを思い出してください (§4.2.3)。)

オペランドが無限大の場合、結果は反対符号の無限大になります。

オペランドがゼロの場合、結果は反対符号のゼロになります。

(鉱山をハイライト)

違いは、発行されたバイトコードで確認できます。単項マイナスは単純なfneg, while(-1f * x)結果はfloadandfmulになり、少し遅くなる可能性があります。

JIT コンパイラーが最適化するかどうかはわかりません。

読みやすくするために、-x通常は を使用する方が優れています。

于 2016-04-25T13:02:02.713 に答える
1

生成されるバイトコードにはわずかな違いがあります。

float one(float x) {
  return -x;
}

float two(float x) {
  return x * -1.f;
}

float three(float x) {
  return -1.f * x;
}

次のように逆コンパイルします。

  float one(float);
    Code:
       0: fload_1
       1: fneg
       2: freturn

  float two(float);
    Code:
       0: fload_1
       1: ldc           #2                  // float -1.0f
       3: fmul
       4: freturn

  float three(float);
    Code:
       0: ldc           #2                  // float -1.0f
       2: fload_1
       3: fmul
       4: freturn

fneg命令はfload_1/fmul;よりもわずかに速いと思います。しかし、違いは無視できる可能性があります (そして、JIT によって最適化される可能性が非常に高いです)。

于 2016-04-25T12:57:58.293 に答える
1

xすでに だった場合float、違いはありません。ただし、の-x方が読みやすいです。

于 2016-04-25T12:53:37.383 に答える