2016-04-25 12 views
0

Javaでは、変数を浮動小数点数から1を引いた値と浮動小数点数を乗じた値との差はありますか?-xとx * -1.0fの間に違いはありますか?

+3

後者は浮動小数点の負数になります。最初は '' x ''の型に依存します。 – npinti

+0

はい、@npintiが指摘しているように、-xは整数型または倍精度型またはxがどんな型であっても-1.0fを乗算すると暗黙的にfloatに変換されます。 – Vucko

+0

@Vucko:はい、しかし、彼は変数もフロートであると書いています。 –

答えて

2

「単項マイナス演算子 - 」xは+0.0である場合ので、我々は浮動小数点値について

ことが判明し、否定は、次いで、ゼロからの引き算と同じではありません0.0-xは+0.0であるが-xは-0.0である。 単項マイナスは、浮動小数点数の符号を単に反転します。関心のある特別なケース:

オペランドがNaNの場合、結果はNaNです。 (NaNには符号がありません(§4.2.3)。

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

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

(ハイライト鉱山)

差は、放出されたバイトコードに見ることができます。単項マイナスは単純なfnegであり、(-1f * x)floadfmulになります。これはおそらくわずかに遅くなります。

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

可読性のために、通常は-xを使用してください。

+0

JavaはIEEE 754-2008に従っていますか? NaNに影響を及ぼすビットレベルの演算として否定を指定します: "5.5.1符号ビット演算実装は、サポートされているすべての算術フォーマットに対して、以下の同種の静穏演算符号ビット演算を提供しなければなりません。この演算では、浮動小数点数とNaNが同様に扱われ、例外はありません。これらの操作は、非正規のエンコーディングを伝播する可能性があります。 [...] negate(x)は、浮動小数点オペランドxを同じ形式のコピー先にコピーし、符号ビットを反転します。 negate(x)は減算(0、x)と同じではありません(6.3を参照)。 – njuffa

+0

IEEE 754-2008では、NaNの符号ビットについてさらに述べています。 "6.3符号ビット。入力または結果がNaNの場合、この規格ではNaNの符号は解釈されません。ビット列 - copy、negate、abs、copySign - 時にはNaNオペランドの符号ビットに基づいてNaN結果の符号ビットを指定します。論理述語totalOrderもNaNオペランドの符号ビットの影響を受けます。 – njuffa

+0

デフォルトでは、Javaはいくつかの自由を取り、精度の高い中間結果を可能にします。 'strictfp'キーワードを使って、JavaはIEEE 754に従いますが、http://stackoverflow.com/questions/11474424/any-ieee754r-compliant-implementations-for-javaによると、Javaは新しい754-2008の亜種を採用しませんでした。 – Polygnome

2

JavaはIEEEのバイナリ浮動小数点表現を使用し、記号は別のビットで表されます。 -1を掛けて、符号を-xに反転することは、この符号ビットをフリップすることによって行われ、残りの表現は変更されません。したがって、-1.0fは正確な表現を持ち、xという表現の精度を変更する可能性がないため、結果に違いはありません。

0

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

1

生産バイトコードに若干の違いがあります:私はfneg命令がfload_1/fmulより若干速いことを想像

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 

;:

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

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

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

逆コンパイルをしますその差はごくわずかです(そして、おそらくJITによって最適化される可能性があります)。 JLS§15.15.4で

関連する問題