37

正しい long 値を取得するために「L」文字を追加する必要があるのはなぜですか? そして、他の価値は何ですか?

long oneYearWithL = 1000*60*60*24*365L;
long oneYearWithoutL = 1000*60*60*24*365;
System.out.println(oneYearWithL);//gives correct calculation result : 31536000000
System.out.println(oneYearWithoutL)//gives incorrect calculation result: 1471228928
4

2 に答える 2

136
long oneYearWithL = 1000*60*60*24*365L;
long oneYearWithoutL = 1000*60*60*24*365;

最初の値は実際には long です (365Lは でlongあり1000*60*60*24、であるため、値を持つ値の結果integerは値です。multiplyinglongintegerlong

しかし、2番目の値は整数です(integer値にinteger値のみを掛けているため、結果は整数になり32-bitます。そのために得られた結果multiplicationは、整数の実際の範囲外です。したがって、変数に割り当てられる前に、有効な整数範囲に収まるように切り捨てられます。

次の print ステートメントを見てください: -

System.out.println(1000*60*60*24*365L);
System.out.println(1000*60*60*24*365);
System.out.println(Integer.MAX_VALUE);

上記のコードを実行すると: -

出力: -

31536000000
1471228928
2147483647

だから、あなたは違いを見ることができます..

011101010111101100010010110000000000 -- Binary equivalent of 1000*60*60*24*365L
    01111111111111111111111111111111 -- Binary equivalent of Integer.MAX_VALUE

したがって、番号の最後にそれを追加しないとL、最上位 4 ビットが最初のバイナリ文字列から削除されます..

したがって、文字列は..

(0111)01010111101100010010110000000000 -- Remove the most significant bits..
      01010111101100010010110000000000 -- Binary equivalent of 1471228928

(出力として取得します)


更新: -上記の説明から、最初の割り当てであっても、乗算する前multiplicationの結果が範囲外になる場合、整数範囲に収まるように切り捨てられるか、に変換される ことも理解できます。必要に応じて、それのみが で乗算されます。integers365L2's complement representationlong value - 365L

例: -

long thirtyYearWithL = 1000*60*60*24*30*365L;

上記の例では、最初の部分 - を考えてみましょう1000*60*60*24*30。この乗算の結果は次のとおり2592000000です。では、それがどのように表されているか見てみましょうbinary equivalent: -

2592000000 = 10011010011111101100100000000000  -- MSB is `1`, a negative value
             01100101100000010011100000000001  -- 2's complement representation

表現の10進表現2's complementは です1702967297。したがって、はに乗算される前に に2592000000変換されます。これ以降、この値は : -に収まるため、それ以上切り捨てられることはありません。-1702967297365Linteger range[-2147483648 to 2147483647]

したがって、実際の結果は次のようになります。

long thirtyYearWithL = 1000*60*60*24*30*365L;
                     = 2592000000 * 365L;
                     = -1702967297 * 365L = -621583063040

typeしたがって、これらすべてのものは、算術演算を適用する際の最終結果の実際を考慮するだけです。そして、このチェックは、移動元の操作の一時的な結果ごとに実行されますleft to right(結合性を持つ演算子を考慮しleft-to-rightて)。一時的な結果が範囲外であることが判明した場合は、次の操作に進む前に、必要な範囲に収まるように適宜変換されます。


更新 2: -

したがって、代わりに: -

long thirtyYearWithL = 1000*60*60*24*30*365L;

最初に移動する365Lと、正しい結果が得られます: -

long thirtyYearWithL = 365L*1000*60*60*24*30; // will give you correct result

なぜなら、あなたのtemporary結果は typelongになり、その値を保持できるからです。

于 2012-10-06T09:08:22.697 に答える
15

計算がなければ、L32 ビット値として実行されます。値を 16 進数で表すと、小さい値は大きい値の下位 4 バイトになります。

Java のデフォルトは 32 ビット整数型です。LongのLは 64 ビットです。Lの後に置くことで365、コンパイラに 365 を値として扱うように指示しlongます。32 ビット値と 64 ビット値が乗算されると、コンパイラは 32 ビット値を 64 ビットにアップキャストして、式を評価する際の中間結果が 64 ビット範囲全体を保持するようにします。

Java 言語仕様プリミティブ型と値を参照してください。

乗算の動作は、次のようにhttps://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.1で明示的に定義されています。

15.17.1 乗算演算子 *

二項*演算子は乗算を実行し、そのオペランドの積を生成します。オペランド式に副作用がない場合、乗算は可換演算です。オペランドがすべて同じ型の場合、整数の乗算は結合的ですが、浮動小数点の乗算は結合的ではありません。整数の乗算がオーバーフローした場合、結果は十分に大きな 2 の補数形式で表される数学的積の下位ビットになります。その結果、オーバーフローが発生した場合、結果の符号は、2 つのオペランド値の数学的積の符号と同じではない可能性があります。

浮動小数点乗算の結果は、IEEE 754 算術の規則によって管理されます。

  • いずれかのオペランドがの場合NaN、結果は になりNaNます。
  • 結果が でない場合、NaN両方のオペランドの符号が同じ場合は結果の符号が正になり、オペランドの符号が異なる場合は負になります。
  • 無限大とゼロの乗算は NaN になります。
  • 有限値による無限大の乗算は、符号付き無限大になります。符号は上記の規則によって決定されます。
  • 無限大も NaN も含まれない残りのケースでは、正確な数学的積が計算されます。次に、浮動小数点値セットが選択されます。
    • 乗算式が FP-strict の場合 (§15.4):
      • 乗算式のタイプが の場合float、浮動小数点値セットを選択する必要があります。
      • 乗算式のタイプが の場合double、double 値セットを選択する必要があります。
    • 乗算式が FP 厳密でない場合:
      • 乗算式の型が の場合float、実装の気まぐれで、浮動小数点値セットまたは浮動小数点拡張指数値セットのいずれかを選択できます。
      • 乗算式の型が の場合double、実装の気まぐれで、double 値セットまたは double-extended-exponent 値セットのいずれかを選択できます。

次に、選択した値セットから製品を表す値を選択する必要があります。

積の大きさが大きすぎて表現できない場合、演算がオーバーフローしたと言います。結果は適切な符号の無限大です。

それ以外の場合、積は、IEEE 754 の最も近い値への丸めモードを使用して、選択された値セットの最も近い値に丸められます。Java プログラミング言語では、IEEE 754 (§4.2.4) で定義されている段階的なアンダーフローのサポートが必要です。

オーバーフロー、アンダーフロー、または情報の損失が発生する可能性があるにもかかわらず、乗算演算子の評価で*実行時例外がスローされることはありません。

于 2012-10-06T09:21:47.313 に答える