「5.1.3. 縮幅プリミティブ変換」の編集履歴(バックアップ)一覧はこちら
「5.1.3. 縮幅プリミティブ変換」(2012/09/14 (金) 14:49:43) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
*[[5. 変換と昇格]]
**[[5.1. 変換の種類]]
***[[5.1.1. 恒等変換]]
***[[5.1.2. 拡幅プリミティブ変換]]
***5.1.3. 縮幅プリミティブ変換
プリミティブ型に対する22の特定の変換が&i(){縮幅プリミティブ変換(narrowing primitive conversion)}と呼ばれます。:
&tt(){short}を&tt(){byte}や&tt(){char}へ変換
&tt(){char}を&tt(){byte}や&tt(){short}へ変換
&tt(){int}を&tt(){byte}や&tt(){short}、&tt(){char}へ変換
&tt(){long}を&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}へ変換
&tt(){float}を&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}、&tt(){long}へ変換
&tt(){double}を&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}、&tt(){long}、&tt(){float}へ変換
縮幅プリミティブ変換は数値の全体的な大きさという情報を失うかもしれません。また、精度や範囲についても失うかもしれません。
&tt(){double}から&tt{float}への縮幅プリミティブ変換は[[IEEE754の丸め規則>4.2.4. 浮動小数点演算]]に従います。この変換では精度や範囲も失う可能性があり、非ゼロ&tt(){double}から&tt(){float}ゼロという結果や有限&tt(){double}から&tt(){float}無限大という結果を生む可能性があります。&tt(){Double}NaNは&tt(){float}NaNに変換されます。&tt(){double}無限大は同じ符号の&tt(){float}無限大に変換されます。
符号付き整数から整数型Tへの縮幅変換は、nを型Tを表すのに必要なビット数とすると、下位nビット以外を単純に切り捨てます。数値の大きさに関する情報を失う可能性に加えて、入力値の符号と異なる符号に変換される可能性があります。
&tt(){char}から整数型Tへの縮幅変換は、同様に、nを型Tを表すのに必要なビット数とすると、下位nビット以外を単純に切り捨てます。数値の大きさに関する情報を失う可能性に加えて、文字は符号なし16ビット整数値で表されるのに、変換結果が負の数となる可能性があります。
浮動小数点数から整数型Tへの縮幅変換は以下の2ステップで行われます。:
+第1ステップで、浮動小数点数はTが&tt(){long}なら&tt(){long}に、Tが&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}なら&tt(){int}に次のように変換されます。:
++浮動小数点数が[[NaN>4.2.3. 浮動小数点型と書式と値]]なら、変換の第1ステップの結果は&tt(){int}か&tt(){long}の&tt(){0}となります。
++そうでなく、浮動小数点数が無限大でなければ、浮動小数点値は[[IEEE754のゼロに向かう丸めモード>4.2.3. 浮動小数点型と書式と値]]を使用してゼロ方向へ丸められ、整数値Vへと丸められます。
+++もしTが&tt(){long}でこの整数値が&tt(){long}で表されるなら、第1ステップの結果は&tt(){long}値Vとなります。
+++そうでなく、この整数値が&tt(){int}で表されるなら、第1ステップの結果は&tt(){int}値Vとなります。
++そうでなければ、以下の2ケースのどちらかが真となります。:
+++値が小さすぎる(負の大きすぎる値や負の無限大)ので、第1ステップの結果は型&tt(){int}か&tt(){long}が表現できる最小の値となります。
+++値が大きすぎる(正の大きすぎる値や正の無限大)ので、第1ステップの結果は型&tt(){int}か&tt(){long}が表現できる最大の値となります。
+第2ステップでは以下が行われます。:
++Tが&tt(){int}や&tt(){long}ならば、第1ステップの結果が変換の結果となります。
++Tが&tt(){byte}や&tt(){char}や&tt(){short}ならば、第1ステップの結果から型Tへ[[縮幅変換>5.1.3. 縮幅プリミティブ変換]]の結果が変換の結果となります。
#divstyle(background-color:#f0f0ff;border:1px solid black;padding 4px){{{
&bold(){&aname(ex5.1.3-1,option=nolink){例5.1.3-1. 縮幅プリミティブ変換}}
class Test {
public static void main(String[] args) {
float fmin = Float.NEGATIVE_INFINITY;
float fmax = Float.POSITIVE_INFINITY;
System.out.println("long: " + (long)fmin +
".." + (long)fmax);
System.out.println("int: " + (int)fmin +
".." + (int)fmax);
System.out.println("short: " + (short)fmin +
".." + (short)fmax);
System.out.println("char: " + (int)(char)fmin +
".." + (int)(char)fmax);
System.out.println("byte: " + (byte)fmin +
".." + (byte)fmax);
}
}
&i(){&small(){このプログラムは以下を出力します。:}}
long: -9223372036854775808..9223372036854775807
int: -2147483648..2147483647
short: 0..-1
char: 0..65535
byte: 0..-1
&i(){&small(){&tt(){char}や&tt(){int}や&tt(){long}は驚くべきことではありません。その型が取りうる最小値と最大値が出力されただけです。}}
&i(){&small(){&tt(){byte}と&tt(){short}は符号と数値の大きさに関する情報が失われており、精度も失っています。結果は&tt(){int}の最大値と最小値の下位ビットだけと考えれば理解できます。最小値の&tt(){int}は16進で&tt(){0x80000000}で、最大値は&tt(){0x7fffffff}です。これは&tt(){short}の場合を考えると下位16ビットだけとなるので、それぞれ&tt(){0x0000}と&tt(){0xffff}となります。&tt(){char}の場合を考えると同じく下位16ビットだけとなるので、それぞれ&tt(){'\u0000'}と&tt(){'\uffff'}となります。&tt(){byte}の場合を考えると下位8ビットだけとなるので、それぞれ&tt(){0x00}と&tt(){0xff}となります。}}
}}}
オーバーフローやアンダーフローやその他の情報の損失を引き起こすにもかかわらず、縮幅プリミティブ変換は実行時に決して例外を発生しません。
#divstyle(background-color:#f0f0ff;border:1px solid black;padding 4px){{{
&bold(){&aname(ex5.1.3-2,option=nolink){例5.1.3-2. 情報を損失する縮幅プリミティブ変換}}
class Test {
public static void main(String[] args) {
// A narrowing of int to short loses high bits:
System.out.println("(short)0x12345678==0x" +
Integer.toHexString((short)0x12345678));
// A int value not fitting in byte changes sign and magnitude:
System.out.println("(byte)255==" + (byte)255);
// A float value too big to fit gives largest int value:
System.out.println("(int)1e20f==" + (int)1e20f);
// A NaN converted to int yields zero:
System.out.println("(int)NaN==" + (int)Float.NaN);
// A double value too large for float yields infinity:
System.out.println("(float)-1e100==" + (float)-1e100);
// A double value too small for float underflows to zero:
System.out.println("(float)1e-50==" + (float)1e-50);
}
}
&i(){&small(){このプログラムは以下を出力します。:}}
(short)0x12345678==0x5678
(byte)255==-1
(int)1e20f==2147483647
(int)NaN==0
(float)-1e100==-Infinity
(float)1e-50==0.0
}}}
***[[5.1.4. 拡幅と縮幅プリミティブ変換]]
***[[5.1.5. 拡幅参照変換]]
***[[5.1.6. 縮幅参照変換]]
***[[5.1.7. ボックス化変換]]
***[[5.1.8. ボックス化解除変換]]
***[[5.1.9. 未検査変換]]
***[[5.1.10. 捕捉変換]]
***[[5.1.11. 文字列変換]]
***[[5.1.12. 禁止変換]]
***[[5.1.13. 値集合変換]]
**[[5.2. 代入変換]]
**[[5.3. メソッド呼び出し変換]]
**[[5.4. 文字列変換]]
**[[5.5. キャスト変換]]
**[[5.6. 数値昇格]]
*[[5. 変換と昇格]]
**[[5.1. 変換の種類]]
***[[5.1.1. 恒等変換]]
***[[5.1.2. 拡幅プリミティブ変換]]
***5.1.3. 縮幅プリミティブ変換
プリミティブ型に対する22の特定の変換が&i(){縮幅プリミティブ変換(narrowing primitive conversion)}と呼ばれます。:
-&tt(){short}を&tt(){byte}や&tt(){char}へ変換
-&tt(){char}を&tt(){byte}や&tt(){short}へ変換
-&tt(){int}を&tt(){byte}や&tt(){short}、&tt(){char}へ変換
-&tt(){long}を&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}へ変換
-&tt(){float}を&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}、&tt(){long}へ変換
-&tt(){double}を&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}、&tt(){long}、&tt(){float}へ変換
縮幅プリミティブ変換は数値の全体的な大きさという情報を失うかもしれません。また、精度や範囲についても失うかもしれません。
&tt(){double}から&tt(){float}への縮幅プリミティブ変換は[[IEEE754の丸め規則>4.2.4. 浮動小数点演算]]に従います。この変換では精度や範囲も失う可能性があり、非ゼロ&tt(){double}から&tt(){float}ゼロという結果や有限&tt(){double}から&tt(){float}無限大という結果を生む可能性があります。&tt(){Double}NaNは&tt(){float}NaNに変換されます。&tt(){double}無限大は同じ符号の&tt(){float}無限大に変換されます。
符号付き整数から整数型Tへの縮幅変換は、nを型Tを表すのに必要なビット数とすると、下位nビット以外を単純に切り捨てます。数値の大きさに関する情報を失う可能性に加えて、入力値の符号と異なる符号に変換される可能性があります。
&tt(){char}から整数型Tへの縮幅変換は、同様に、nを型Tを表すのに必要なビット数とすると、下位nビット以外を単純に切り捨てます。数値の大きさに関する情報を失う可能性に加えて、文字は符号なし16ビット整数値で表されるのに、変換結果が負の数となる可能性があります。
浮動小数点数から整数型Tへの縮幅変換は以下の2ステップで行われます。:
+第1ステップで、浮動小数点数はTが&tt(){long}なら&tt(){long}に、Tが&tt(){byte}や&tt(){short}、&tt(){char}、&tt(){int}なら&tt(){int}に次のように変換されます。:
++浮動小数点数が[[NaN>4.2.3. 浮動小数点型と書式と値]]なら、変換の第1ステップの結果は&tt(){int}か&tt(){long}の&tt(){0}となります。
++そうでなく、浮動小数点数が無限大でなければ、浮動小数点値は[[IEEE754のゼロに向かう丸めモード>4.2.3. 浮動小数点型と書式と値]]を使用してゼロ方向へ丸められ、整数値Vへと丸められます。
+++もしTが&tt(){long}でこの整数値が&tt(){long}で表されるなら、第1ステップの結果は&tt(){long}値Vとなります。
+++そうでなく、この整数値が&tt(){int}で表されるなら、第1ステップの結果は&tt(){int}値Vとなります。
++そうでなければ、以下の2ケースのどちらかが真となります。:
+++値が小さすぎる(負の大きすぎる値や負の無限大)ので、第1ステップの結果は型&tt(){int}か&tt(){long}が表現できる最小の値となります。
+++値が大きすぎる(正の大きすぎる値や正の無限大)ので、第1ステップの結果は型&tt(){int}か&tt(){long}が表現できる最大の値となります。
+第2ステップでは以下が行われます。:
++Tが&tt(){int}や&tt(){long}ならば、第1ステップの結果が変換の結果となります。
++Tが&tt(){byte}や&tt(){char}や&tt(){short}ならば、第1ステップの結果から型Tへ[[縮幅変換>5.1.3. 縮幅プリミティブ変換]]の結果が変換の結果となります。
#divstyle(background-color:#f0f0ff;border:1px solid black;padding 4px){{{
&bold(){&aname(ex5.1.3-1,option=nolink){例5.1.3-1. 縮幅プリミティブ変換}}
class Test {
public static void main(String[] args) {
float fmin = Float.NEGATIVE_INFINITY;
float fmax = Float.POSITIVE_INFINITY;
System.out.println("long: " + (long)fmin +
".." + (long)fmax);
System.out.println("int: " + (int)fmin +
".." + (int)fmax);
System.out.println("short: " + (short)fmin +
".." + (short)fmax);
System.out.println("char: " + (int)(char)fmin +
".." + (int)(char)fmax);
System.out.println("byte: " + (byte)fmin +
".." + (byte)fmax);
}
}
&i(){&small(){このプログラムは以下を出力します。:}}
long: -9223372036854775808..9223372036854775807
int: -2147483648..2147483647
short: 0..-1
char: 0..65535
byte: 0..-1
&i(){&small(){&tt(){char}や&tt(){int}や&tt(){long}は驚くべきことではありません。その型が取りうる最小値と最大値が出力されただけです。}}
&i(){&small(){&tt(){byte}と&tt(){short}は符号と数値の大きさに関する情報が失われており、精度も失っています。結果は&tt(){int}の最大値と最小値の下位ビットだけと考えれば理解できます。最小値の&tt(){int}は16進で&tt(){0x80000000}で、最大値は&tt(){0x7fffffff}です。これは&tt(){short}の場合を考えると下位16ビットだけとなるので、それぞれ&tt(){0x0000}と&tt(){0xffff}となります。&tt(){char}の場合を考えると同じく下位16ビットだけとなるので、それぞれ&tt(){'\u0000'}と&tt(){'\uffff'}となります。&tt(){byte}の場合を考えると下位8ビットだけとなるので、それぞれ&tt(){0x00}と&tt(){0xff}となります。}}
}}}
オーバーフローやアンダーフローやその他の情報の損失を引き起こすにもかかわらず、縮幅プリミティブ変換は実行時に決して例外を発生しません。
#divstyle(background-color:#f0f0ff;border:1px solid black;padding 4px){{{
&bold(){&aname(ex5.1.3-2,option=nolink){例5.1.3-2. 情報を損失する縮幅プリミティブ変換}}
class Test {
public static void main(String[] args) {
// A narrowing of int to short loses high bits:
System.out.println("(short)0x12345678==0x" +
Integer.toHexString((short)0x12345678));
// A int value not fitting in byte changes sign and magnitude:
System.out.println("(byte)255==" + (byte)255);
// A float value too big to fit gives largest int value:
System.out.println("(int)1e20f==" + (int)1e20f);
// A NaN converted to int yields zero:
System.out.println("(int)NaN==" + (int)Float.NaN);
// A double value too large for float yields infinity:
System.out.println("(float)-1e100==" + (float)-1e100);
// A double value too small for float underflows to zero:
System.out.println("(float)1e-50==" + (float)1e-50);
}
}
&i(){&small(){このプログラムは以下を出力します。:}}
(short)0x12345678==0x5678
(byte)255==-1
(int)1e20f==2147483647
(int)NaN==0
(float)-1e100==-Infinity
(float)1e-50==0.0
}}}
***[[5.1.4. 拡幅と縮幅プリミティブ変換]]
***[[5.1.5. 拡幅参照変換]]
***[[5.1.6. 縮幅参照変換]]
***[[5.1.7. ボックス化変換]]
***[[5.1.8. ボックス化解除変換]]
***[[5.1.9. 未検査変換]]
***[[5.1.10. 捕捉変換]]
***[[5.1.11. 文字列変換]]
***[[5.1.12. 禁止変換]]
***[[5.1.13. 値集合変換]]
**[[5.2. 代入変換]]
**[[5.3. メソッド呼び出し変換]]
**[[5.4. 文字列変換]]
**[[5.5. キャスト変換]]
**[[5.6. 数値昇格]]
表示オプション
横に並べて表示:
変化行の前後のみ表示: