入門じゃないJava(4)
おはようございます。
今日も楽しくJavaを見ていきましょう。
前回(昨日)は書き終わらず見苦しいところをお見せしてしまいすいませんでした。
加筆の方も終わりましたので、「なんだこれは」と思われた方は、最後の部分だけ今一度ご覧いただければと思います。
さて、今日は前回のキャストのお話を完結させようと思います。
まずは基本型の拡大変換と縮小変換についてみていきます。
基本型の拡大変換と縮小変換
以下の変換は、基本型の拡大変換と縮小変換は2段階で行われます。
byteからcharへの変換
まず最初に、byteは基本型への拡大変換によってint型へと変換され、その後、基本型の縮小変換によってintからcharへと変換されます。
strictfpとFP厳密式
浮動小数点数の内部は複雑であるため、すべての実行環境で浮動小数点数の演算結果がピッタリと一致するわけではありません。というもの、厳密にIEEE745形式で表せる値のみを利用するような演算を行おうとすると、ハードウェア資源を十分に活用できなくなり、演算に時間がかかってしまうからです。
たとえば、intelのCPUの場合、浮動小数点数は内部的に80ビットで演算をする仕様になっており、それを利用した高速な演算が行われます。
実行環境に依存することなく、同じ演算結果を得られるようにするには、特別な宣言が必要です。
クラス宣言(第8章)・インタフェース(第14章)・メソッド宣言(第7章)にstrictfpというキーワードを指定します。たとえば、クラス宣言に指定する場合は以下のようになります。
//クラスABC内のすべての浮動小数点式をFP厳密にする strictfp class ABC { //... }このように宣言されたクラス(やインタフェース)の中では、すべての浮動小数点式はFP厳密(FP-strict)となります。その場合、、実行環境に依存することなく、同一の演算結果が得られることが保障されます。
FP厳密の場合、floatからdoubleへの拡大変換では、変換前後の数値の大きさが変化することはありません。その一方で、FP厳密でなければ、変換後の数値の大きさに関する情報が欠落する可能性があります。
なお、クラス中の特定のメソッドのみをFP厳密にする必要があれば、そのメソッドにstrictfpをつけます。
//メソッドf内のすべての浮動小数点式をFP厳密にする。 strictfp void f() { //... }クラス・インタフェース・メソッドにstrictfpがつけられていなくても、0.0や3.14のような定数に限っては、必ずFP厳密になることが保障されています。
*
通常の計算ではFP厳密にする必要は、それほどありません。厳密にIEEE 754形式にのっとた演算を行う必然性があるときのみ、指定するといいでしょう。
柴田 望洋 (2016) .『新・明解Java入門』p167 Columu 5-8より
かぼす的解説
strictfpはストリクトエフピーと読みます。ちなみにIEEEはアイ トリプル イーと読むとかっちょいいでしょう。アイ イー イー イーと言ってるとアイーン!って言っちゃいそうですからね。
と、今日はここまでにしましょう。
次回は拡張表記について学んでみましょう。
では!
参考文献
柴田 望洋 (2016) .『新・明解Java入門』167-169
入門じゃないJava(3)
こんばんは。
ちょっとこの記事を書くのには時間が遅いので、今日中に書ききれるか不安ですが、今回も楽しくJavaを見ていきましょう。
ちなみに、前回は浮動小数点数などを見ていきましたね。
今回は整数型、浮動小数点型を見てきたので、キャスト演算子などを通して型変換を見ていきましょう。
キャスト演算子
キャスト演算子のフォーマットは次の通りです。
( 型 ) 式
そのため、たとえばint型のintValueをdouble型に変換しdouble型のdblValueに代入するときは、
dblValue = (double) intValue;
となります。
お分かりかとは思いますが、ここで使われる( )は区切り子ではなく、キャスト演算子です。なお、このような型変換はキャストと呼ばれます。
このキャスト演算子は変数だけでなく、数値リテラルを指定することもできます。
dblValue = (double) 12;
とすれば結果は12.0になります。
また、
dblValue = (double) (a + b);
で、aを7、bを8とし、得られた結果が15の時、このキャスト式を評価すると15.0になります。
基本型の縮小変換
縮小変換は原則としてキャストが必須。
変換に伴い、数値の大きさ(指数部)、数値の精度(仮数部)の情報が欠損する場合があります。
キャストを伴わない縮小変換
基本型の縮小変換では原則的にキャストが必須ですが、一部例外があります。
byte a = 2;
a = 12;
short b = 53;
以前学習した整数接尾語L(または"l"小文字のエル)のつかない整数リテラルはint型です。
したがって、byte型やshort型に対して、int型である2,12,53の値を入れる際にはキャストが必要なはずです。が、キャストをしなくてもエラーにならないのは以下のような規則があるからです。
代入の右辺の式や書式指定子がbyte、short、char、int型の定数式で、代入先あるいは初期化先の変数の型がbyte、short、charであって、定数式の値が変数の型で表現できる場合は、基本型の縮小変換が自動的に行われる。
キャストせずに入れることができるのは、定数式と定数式の値が変数の型で表現できる場合に限られます。
short a = 12; //Pass
byte b = a; //Error
byte c = 128; //Error
なお、浮動小数点型にはこのような規則はありません。したがって、float型の変数に対して、キャストすることなく、double型の定数値を入れることはできません。
float a = 3.14; //Error
float b = (float)3.14; //Pass
float c = 3.14f; //Pass
基本型の拡大変換
前項の「基本型の縮小変換」の逆がこれ、「基本型の拡大変換」です。
例は柴田 望洋 (2016) .『新・明解Java入門』p166でご確認ください。
この変換は代入あるいは初期化の際に自動的に行われます。例を以下に示します。
int a = '5'
long b = a;
double = 3.14f;
基本型の拡大変換では、数値の大きさに関する情報は原則として失われないことになっています。ただし、以下に示す例については精度を失うことがあります。
int あるいは long 型の値からの floatへの変換
long の値からdoubleへの変換。
この場合、浮動小数点の変換結果は最も近い値に丸められた整数値になります。
以下の拡大変換の例では精度を失います。
class IntegralToFloat { public static void main(String[] args) { int a = 123456789; long b = 1234567890123456789L; System.out.println(" a = " + a); System.out.println(" (float) a = " + (float)a); System.out.println(" b = " + b); System.out.println("(double) b = " + (double)b); } }
実行結果
a = 123456789
(float) a = 1.23456792E8
b = 1234567890123456789
(double) b = 1.23456789012345677E18
C:\Java\03>_
intからfloatに変換する過程と、longからdoubleに変換する過程で精度に関する情報が欠損したことがわかります。
今日はここまで!
参考文献
柴田 望洋 (2016) .『新・明解Java入門』162-166
今日のこと
こんばんは。
もやもやのかぼすです。
久しぶりに「今日のこと」というエントリーですが、激動の一日でした(?)
朝はバイナリとの格闘、昼はAntirollback versionとの格闘、そして、現在hard brickに至る。
と、一喜一憂していました。
おそらく、大半の方は「何のこっちゃ」という感じだと思います。
僕も今そんな感じです。
朝から、ファクトリーイメージを書き換えて、昼は、焼いたファームウェアがそれ以外に書き換わらなくなって、夜(現在)、ダメもとで焼いたらhard brickしてしまった。
という具合です。
実におまぬけな一日です。
今日は気持ちよく寝れるはずだったのですが。。。
では!
ROM焼きというかDD
こんばんは。
いつもながらのかぼすです。
今日はJavaではなくほとんどROM焼きをしていました。
ロム焼きというか結局ddコマンドとpull、fastbootにしたり、bootloopに陥ったのでROMを書き戻したり、を繰り返していました。
いつかそんな話もしたいんですけどね。。。
では!