-x 与 x * -1.0f 之间有区别吗?

Is there a difference between -x vs x * -1.0f?

在 java 中,如果变量也是浮点数,取负变量与将变量乘以浮点数减一之间有区别吗?

Java 使用 IEEE 的二进制浮点表示法,符号由单独的位表示。乘以 -1 和用 -x 反转符号都是通过翻转这个符号位来完成的,同时保持表示的其余部分不变。这就是为什么结果没有差异的原因,因为 -1.0f 具有精确的表示,并且没有机会更改 x.

的表示精度

如果 x 已经是 float 那么就没有区别了。然而 -x 更具可读性。

生成的字节码略有不同:

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 优化)。

在 JLS §15.15.4 "Unary Minus Operator -" 中,我们发现

For floating-point values, negation is not the same as subtraction from zero, because if x is +0.0, then 0.0-x is +0.0, but -x is -0.0. Unary minus merely inverts the sign of a floating-point number. Special cases of interest:

If the operand is NaN, the result is NaN. (Recall that NaN has no sign (§4.2.3).)

If the operand is an infinity, the result is the infinity of opposite sign.

If the operand is a zero, the result is the zero of opposite sign.

(突出显示我的)

可以在发出的字节码中看出差异。一元减号是一个简单的 fneg,而 (-1f * x) 导致 floadfmul,这可能稍微慢一些。

我不知道 JIT 编译器是否会优化它。

为了可读性,使用 -x 通常更好。