質問

なぜこの Java コードは

long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);

実行時に出力する

1
1
107374182400
0

予想される代わりに

1
1
107374182400
107374182400

出力?

役に立ちましたか?

解決 2

107374182400は、整数の全範囲の正確な25倍です(2^32), 、つまり、整数に合わせようとすると オーバーフロー. 。そして、それは正確に25倍適合するため、0で正確になります(これは偶然であり、他の巨大な乗算は正または負になる可能性があります)。そして、あなたはあなたが長くキャストしたポイントまで整数を使用しています

long a1 = 100 * 1024 * 1024 * 1024;

に相当します

int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;

表現に1つの長い時間をかけた場合、問題を削除する整数数学ではなく長い数学を使用することを余儀なくされます

他のヒント

 long a2 = 100L * 1024 * 1024 * 1024;

ただし、この操作では少なくとも 1 つのオペランドは long. 。したがって、演算は 64 ビット精度を使用して実行され、数値演算子の結果は次の型になります。 long. 。他の非長いオペランドはタイプに広がっています long による 数値的なプロモーション 結果の値は変数に格納されます a2.

 long a1 = 100 * 1024 * 1024 * 1024;

単純な整数の定数式。式の結果は型として計算されます。 int. 。ただし、計算された値が大きすぎて整数に収まらないためオーバーフローし、次のような結果が得られます。 0 に保存されます a1 変数。

編集:次のコメントで尋ねられているように:

なぜマイナスにならないのでしょうか?

なぜなら、中にいる間は 整数計算 2 番目の計算は次と同等です 25 * 2^32 どこ ^ パワーの意味があり、 2^32 整数値は 0. 。ただし、なぜその価値があるのか​​を説明すると、 0:バイナリでは:

 100 * 1024 * 1024 * 1024 == 25 * 2^32;

 Integer.MAX_VALUE =  2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
 Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000 

2 ^ 31 は負の整数(-2147483648) 符号ビットとして 1 それゆえ 2 ^ 32 は単なる乗算です 22 ^ 31:左シフトすると、符号ビットは次のようになります 0 したがって、結果は次のようになります 0.

をチェックしてください java language specification: 4.2.2: Integer operation 詳細については。

それは、の右側の表現かもしれません a1 最初に計算されます int そして後に変換されました long. 。それが等しい場合 0 として int それはとどまります 0 として long

に従って 語彙文字の文書 それは言及されています、

リテラルのタイプは次のように決定されます。
-LまたはLで終わる整数リテラル(§3.10.1)のタイプは長い(§4.2.1)。
- 他の整数リテラルのタイプはint(§4.2.1)です。

したがって、あなたの表現、 100 * 1024 * 1024 * 1024 として評価されます int 原始的なデータ型のため l また L 数値では言及されていません。結果は次のとおりです 107374182400 つまり、バイナリでです 1 1001 0000 0000 0000 0000 0000 0000 0000 0000int 32ビットは低い32ビットで、で言及されているように撮影されます 例4.2.2-1。整数操作 結果 0

また、同じドキュメントで言及されています。

シフト演算子以外の整数演算子に少なくとも1つのオペランドが長い場合、操作は64ビット精度を使用して実行され、数値演算子の結果は型長いです。他のオペランドが長くない場合、数値プロモーションでLONGを入力するために最初に拡大されます(§5.1.5)

それは、式の任意の値が含まれることを意味します l また L それからすべて int 値は64ビットに拡張されます。

編集コメント それも尋ねられます

なぜネガティブにならないのですか?

私もそうだと思います 上記の質問に答えます

long a4 = 1L; //これで問題ありません

long a3 = 1; //ここで左側の原始は整数と見なされ、割り当ての時点でそれは長くキャストされるので、再び結果は期待どおりです

long a2 = 100L * 1024 * 1024 * 1024; (ここでは100Lを使用しているので、他のタイプは長い間予想される出力にキャストされます)

long a1 = 100 * 1024 * 1024 * 1024; (デフォルトでは、原始桁はJavaのINTと見なされているため、これを整数増殖と見なすため、範囲外に出て0になります。

これがあなたがしたことです:あなたは割り当てました 100 * 1024 * 1024 * 1024長いデータ型にしかしあなたはそうしなかった」 100 * 1024 * 1024 * 1024 長い値です

デフォルトでは、Java Compilerは整数だと考えています。 Integerはそれほど価値を保持できないため、間違った結果が表示されます。それが役に立てば幸い !

理由は 整数オーバーフロー
の出力として 100 * 1024 * 1024 * 1024; 整数です(int) いいえ long

とで long a2 = 100L * 1024 * 1024 * 1024; 値の1つがあることを指定しています long (ここ 100L)およびその値での乗算はです long 正しく保存される値 a2

Javaでは、int * intがある場合、出力をintとして計算します。 int * longを行う場合にのみ、結果が長いとされます。あなたの場合、100 * 1024 * 1024 * 1024がINTをオーバーフローする結果をもたらします。

したがって、「L」を追加すると、オペランドが長くなり、計算は値を長く保存します。そしてもちろん、オーバーフローは発生せず、正しい結果を出力できます(つまり、A2)。

3番は、100Lの長いタイプを指定したために機能しました。それがそれが長い乗算であり、保存することができる理由です。一方、ナンバー4は最大値2^32-1の整数増殖です。そのため、オーバーフローが得られ、ゼロのデフォルトの価値が表示されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top