アルゴリズムとプログラミング (Algorithms and Programming) 第2回:Javaの変数と演算子 •変数(variable)とは •変数の型(type) •変数の宣言と初期化 •変数への値の代入 •型変換(cast) •Javaの演算子(operator) •(補足)文字型の取り扱い 講義資料等: http://www.pe.titech.ac.jp/~watanabe/lecture/ap/index-j.html Java開発環境の準備 Javaのインストール http://java.sun.com/javase/downloads/index.jsp • Downloads ⇒ JDKのMulti-language版を選択 • 最新版をインストールしてください • NetbeansなどのIDEは必須ではない • 環境変数の登録を忘れずに • 手になじんだテキストエディターを準備して.. さあ、はじめよう!! コンパイルのチェック • テキストエディタで作成:FirstProgram.java class FirstProgram { public static void main(String[] args) { System.out.println(”Hello World!”); } } • 保存したらコンパイル javac FirstProgram.java • 実行 java FirstProgram ↲ ↲ 変数とは 変数:データを格納するメモリ領域(読み書き可能) (コンパイラは,メモリ領域の先頭番地を,変数aな どの識別子に対応付けている) 例) a = 3; aという識別子に対応付けられた メモリ領域に,値3を代入する 0 0 0 0 0 0 1 1 変数を定義するには,まずそのビット数を 定めなければならない. 型(type):変数に格納する値の種類が規定される (ビット数とその解釈) Javaで定義されている基本型(type) 型の名称 ビット数 boolean 1 char byte 16 short 16 int 32 -231~231-1 (-2147483648~ 2147483647) 符号付整数 long 64 -263~263-1 (-9223372036854775808 ~ 9223372036854775807) 符号付整数 float 32 ±3.40282347E+38~ ±1.40239846E-45 浮動小数点数 double 64 ±1.79769313486231570E+308~ ±4.94065645841246544E-324 浮動小数点数 8 値の範囲 説明 true or false 真偽値 \u0000~\uFFFF 文字コード(Unicode規格)に対応 -27~27-1 (-128~127) 符号付整数 -215~215-1 (-32768~32767) 符号付整数 変数の宣言=メモリ領域の確保 例) byte型の変数bを宣言する 記法: byte b; メモリ アドレス 0000 0001 0002 0003 0004 0005 34 AF 21 D1 04 7F FFFE 00 FFFF BB 8bit分のデータ を格納する領域 コンパイラが、 変数bの値を格納する メモリ領域を確保する (コンパイラの仕事. プログラマは宣言するだけ.) byte型(8bit)の値の範囲 表現できる値の個数は? →28 (=256)個 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ●10進数で0~255 1 1 1 1 1 1 1 0 ●byte型は符号付整数なので, 正負半分ずつにふり分けて -128~127 1 1 1 1 1 1 1 1 最上位ビットが1なら負数 負数の求め方→2の補数表現 -1の2進数表現を求める • 1の2の補数をとる 1= 0 0 0 0 0 0 0 1 ビット反転 1 1 1 1 1 1 1 0 +1 1 1 1 1 1 1 1 1 ー1の2進数表現 コンピュータの内部表現なので,プログラマーは通常意識する必要は無い byte型の値の範囲(-128~127) この範囲では符号付きと符号無しは一致 (符号無し整数) 128 129 130 255 0 1 2 126 127 -128, -127, -126,..., -1, 0, 1, 2, ...,126, 127 (符号付き整数) int型やlong型も同様 2進数の小数表記 23 22 21 20 2-1 2-2 2-3 2-4 1101 1001 23+22 + 20 + 2-1 二進数 0.1000 0.0100 0.0010 0.0001 十進数 2-1 = 0.5 2-2 = 0.25 2-3 = 0.125 2-4 = 0.0625 + 2-4 浮動小数点(floating point) 表記の例: 3.14 6.02E+23 (→6.02×1023) (仮数部)×2(指数部) の形に変換し, (仮数)と(指数)をビット列としてメモリに保存 浮動小数点数の宣言と値の代入: double x, y ; float z = 2.05 ; float型のビット構成 (IEEE754規格32bit浮動小数点数) ビットレイアウト 低位桁 高位桁 222 263 符号部S(1bit) 指数部e(8bit) 符号S 1. 仮数k × 2 指数 2進数表記 (1) S (1 仮数部k(23bit) 指数部の2進数表現 float値への変換 0: + 1: - 24 23 21 20 k e 127 ) 2 223 0は、符号部、仮数部、指数部=0で表現 無限大、無限小の表現も定義されている ... 1000 0011 1000 0010 1000 0001 1000 0000 0111 1111 0111 1110 0111 1101 0111 1100 ... +4乗 +3乗 +2乗 +1乗 0乗 -1乗 -2乗 -3乗 127(10) 8bit指数部の値から 127を引いた値が 実際の指数を表す float値(32bit)のビットレイアウトを表示する Javaプログラム FloatingPoint.java class FloatingPoint { public static void main(String[] args) { // 引数文字列 args[0] を float 型に変換 float f = Float.parseFloat(args[0]); // float 型 f のビット表現を文字列 str に変換 String str = Integer.toBinaryString(Float.floatToRawIntBits(f)); System.out.println(args[0] + " = " + str); } } C:\java>javac FloatingPoint.java C:\java>java FloatingPoint 21.6875 21.6875 = 1000001101011011000000000000000 C:\java>java FloatingPoint -21.6875 -21.6875 = 11000001101011011000000000000000 (注意:上位桁の0は表示されないので、32bitに足りない分は上位桁に0を補う) 32bitのビットレイアウト(int値)をfloat値に変換して 表示するJavaプログラム IntBitsToFloat.java class IntBitsToFloat { //与えられたint値をIEEE754浮動小数点数 //(32bit)のビットレイアウトと見なしてfloat値に変換するプログラム //ラッパークラスにあらかじめ用意されているメソッドを使う public static void main(String[] args) { int i=0xC0E0000 ; //与えられたint値(32bit以内) System.out.println( "与えられたint値(16進数)=" + Integer.toHexString(i) ); System.out.println( "与えられたint値(2進数)=" + Integer.toBinaryString(i) ); System.out.println( "float値=" + Float.intBitsToFloat( i ) ); } } double型のビット構成 (IEEE754規格64bit浮動小数点数) ビットレイアウト 低位桁 高位桁 263 251 符号部S(1bit) 指数部e(11bit) 24 23 21 20 仮数部k(52bit) double値への変換 符号 1. 仮数 0: + 1: - 2進数表記 × 2 指数 k e 1023 (1) (1 52 ) 2 2 S 変数の宣言と値の代入 int i ; i=0; int i = 0 ; 宣言(型と変数名を決める) 値の代入(=は代入演算子) 意味は上と同じ 0=i; セミコロンは文の終わりを表す. 忘れると文が次の行まで続いて いることになってしまうので注意! 識別子の命名規則 変数名,クラス名など • 使える文字は半角文字の英字・数字・アンダースコア「_」に 限定(例外は多いが避けた方が無難) • 半角英字の大文字・小文字は区別される • 数字で始まる識別子は認めない • キーワード(keyword)と呼ばれるJavaの予約語と、true・ false・nullの3単語は使用できない。(他の語句と組み合わ せれば可) • 長さに制限はない サンプルプログラム(宣言と代入) ファイル名:Sample1401.java class Sample1401 { public static void main(String[] args) { int型の変数aを宣言する int a; int b = 10; int型の変数bを宣言し、値10を代入する a = 200; b = 100; System.out.println(”変数a”); System.out.println(a); System.out.println(”変数b”); System.out.println(b); } この表記法に関しては後の講義で } コンパイル: javac Sample1401.java 実行: java Sample1401 クイズ: 下記プログラムの実行結果は? ファイル: AP0201.java class AP0201 { public static void main(String[] args) { int i = 2147483647 ; intの最大値 i = i + 1 ; System.out.println(i); } } 実行結果: -2147483648 教訓:最大値に留意して変数の型を選択せよ! 数値リテラル(定数)の表記法 整数リテラル l(小文字のエル)でも可だが L が推奨 long i = 200L ; (明示的にlong型であることを指定する) int i = 200 ; (何も指定しなければint型とみなされる) 10進数リテラル 1234 8進数リテラル 01234 (先頭に0を付加する) 16進数リテラル 0x1234 (先頭に0xを付加する) 浮動小数点リテラル 何も指定しなければdouble double x = 1.0, y = 6.02e+23, z = 1.23d ; float y = 2.0f ; 指数の表記 式の構成 • 演算は式によって記述される • 式はオペランドと演算子で構成される 1+3 や i + 10 など • 式には型があり、(演算の結果)値を持つ i= i+3 ; i=a-b ; その結果を代入文や比較文で利用 • 代入文は値を持つ(値は代入された値) x=y=z=3 ; → 多重代入式 式の値と型 すべての式は、型と値を持つ int a=1, b; b = 24 * a; ← この行全体は変数bへの代入式だが、右辺だけで も“式”であり、型と値を持っている。 1)まずオペランドの型を全て調べ、式の型を決める。 この場合はint型と判断される。 2)次に、それぞれのオペランドの値を確定(評価)する。 定数はそのままの値だが、強制的に式の型にはめら れることに注意せよ。変数の場合は、その時点で格納 されている値を採用する。 3)それらの値を用いて演算を実行し、その結果を右 辺の式の値とする。 4)その値がbに代入される。 こんな単純な式でも、Java VMがやっていることは意外と手が込んでいる!! 注意! 下記プログラムは意図し た動作をしない! long i = 24 * 60 * 60 * 1000 * 1000 ; (マイクロ秒単位の1日の長さ) 代入したい数値は 86400000000 である。int値の範囲からは逸 脱しているがlong値の範囲内には入っている。一見正しそうだが。 右辺の型がintと判断されるので、演算はint型で実施される。 86400000000 はオーバーフローし、予期しない値がlongに拡張型 変換されて 変数 i に代入される。 演算子と優先順位 優先順位 演算子 説明 ++ インクリメント ( + 1 ) -* ディクリメント ( - 1 ) 高い 乗算 / 除算 % 剰余 + 加算 - 減算 += 加算代入 -= 減算代入 *= 乗算代入 /= 除算代入 %= 剰余代入 低い (同一グループ内の優先順位は同じ) 多重代入式の動作 (右から左へ) 記述 解釈 a += b = c ; b=c; a=a+b; a = b += c ; b=b+c; a=b; a += b -= c ; b=b-c; a=a+b; インクリメント演算子 数値型変数のみに使える 後置 a++ 評価 加算 (1)(a++)の値としてaの値を採用する (2)変数aの値に1を加算する (a++)をaの中身の 値で置き換える 前置 ++a 加算 評価 (1)変数aの値に1を加算する (2)加算した結果を(++a)の値として採用する 値の評価と加算の順序が異なる!! インクリメント演算子と代入文 b = a++ ; 評価 加算 (1)(a++)の値としてaの値を採用する インクリメント 演算子の実行 (2)変数aの値に1を加算する (3)(1)で採用した(a++)の値をbに代入する b = ++a ; 加算 評価 int tmp = a ; a=a+1; b = tmp ; (1)変数aの値に1を加算する (2)加算した結果を(++a)の値とする (3)(2)で確定した値をbに代入する 代入演算子の 実行 a = a+1; b=a ; 実行後のaの値は同じだが、bの値は異なる!! ++、ーー演算子を含む式の実行 (オペランドの値の決定と演算順序に関する注意) a=2; b = --a * a ; a=2; b = a-- + --a ; a=2; b = a * --a ; a=2; b = a + --a * a; a=2; b = a + a * --a; a=2; b = --a + a * a ; // b=1 // b=2 // b=2 // b=3 // b=4 // b=2 •演算順序としては++,- -が一番早いが、オペランドの値の評価は式の左か ら行われる •式のオペランドは、左から順に値を決めていく。値が決まったら演算順序 に従って演算を実行する。値を決める際に++,--が反映するので++,--の演 算順序が早いといわれるが、実際にはオペランドの値は式の左から順に決 まっていくのである。 (問題) a=2; b = a-- + --a ; bの値はいくつ? 1.まず右辺が評価される (a--) + (--a) オペランドの値を左から順に確定(評価)していく。まずはa - - から。 aの値は2なので、(a--)の値は2と評価される (問題) a=2; b = a-- + --a ; bの値はいくつ? 1.まず右辺が評価される ( 2 ) + (--a) オペランドの値を左から順に確定(評価)していく。まずはa - - から。 aの値は2なので、(a--)の値は2と評価される デクリメント 演算子の動作 その直後、aの値は1減算され、aの値は1となる 次に(--a)の値が評価される。前置演算子なので (--a)の値は1-1で0と評価される。 (問題) a=2; b = a-- + --a ; bの値はいくつ? 1.各オペランドの値が確定した! (2)+(0) =2 結果として、演算 (2) + (0) が実行され、右辺の式の値は2と確定する。 2. 代入演算子により右辺の式の値2が左辺のbに代入される。 ∴b=2 (答え) その他の代入演算子 i += 3 ; i=i+3; a *= 0.5 ; a = a * 0.5 ; a *= b + 1 ; a=a*(b+1); 演算子 演算子 説明 + 加算 * 減算 (あるいは正負の符号反転) / 除算 % 剰余 ++ インクリメント ( + 1 ) -- ディクリメント ( - 1 ) += 加算代入 -= 減算代入 *= 乗算代入 /= 除算代入 %= 剰余代入 乗算 型が異なる変数の代入 型の違う変数の代入 int a = 0 ; long b = 0; b=a; a =b; OK エラー!! 値を比較しているの ではなく、型の大きさ だけで判断 代入 桁あふれ (byte) 0 0 0 0 0 0 0 0 (short) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 型変換 double d = 0.1; int i = 1 ; long ii = 3; ii = i ; d = (double) i ; ii = d; サイズ小→サイズ大 への代入は暗黙に 行われる 強制的に指定の(型)へ 変換して代入≡型変換 ( )→キャスト演算子 longとdoubleはビット数は等しいが 表現する値の範囲がdoubleの方が 広いため、コンパイルエラー 型変換の注意 int i = 1; long ii = 3; i = (int)ii ; 強制的に型変換すると サイズ大→サイズ小 の代入ができてしまうが 情報が失われる可能性 に注意せよ! 暗黙の型変換(演算の場合) 2つのオペランドの型を比べて,小さい方のオペランド の型を,大きい方のオペランドの型に変換してから 演算する.(同じ型なら変換せずに演算) double d ; int i = 1; d=1/2; d=0 d = 0.5 * i ; d = 0.5*(double)1=0.5 d = i – d ; d = (double)1 – 0.5 = 0.5 文字型(char型) char型は16bitの整数値を持ち,Unicodeとの 対応表により1文字を表現するのに使われる char c1, c2; c1 = ‘1’ ; c2 = ‘a’ ; c1 = ‘ ‘ ; • ‘ ‘は,文字定数(リテラル)を意味する. • 文字’1’に対応する16bit値(Unicode)が c1に格納される • 空白(スペース)も立派な1文字である 半角スペースと全角スペースは異なるUnicode 複数の文字の並び(=文字列)は,1つのchar型 値では表現できない! char c1=‘ab’; 文法エラー 文字列リテラル(定数) class FirstProgram { public static void main(String[] args) { System.out.println(”Hello World!”); } } 文字列リテラル “Hello World!” ダブルクォーテーションで文字列を囲む この文字列を格納するのに必要なメモリサイズは char型のサイズ(16bit) × 文字数 char型変数を複数用意する必要がある⇒配列,Stringクラス等,後述 特殊文字(エスケープシーケンス) エスケープシーケンス 機能 \b バックスペース \t \n \f \r タブ文字 \” ダブルクオーテーション \’ シングルクオーテーション \\ 「¥」の文字そのもの \0 8進数で表した文字コード(0は0~7までの数字1文字) \00 8進数で表した文字コード(00は0~7までの数字2文字) \T00 8進数で表した文字コード(Tは0~3までの数字1文字,00は0~7までの数字2 文字≡1byte分256文字の8進数表現) \uXXXX ユニコード文字(XXXXは4桁の16進数表記) 改行 フォームフィード 復帰 クイズ: 下の四角で囲った文を出力するJavaプログラムを書きなさい。 ”\\”は”\”そのものを表す (“や\は半角文字とする) 解答例:AP0301.java class AP0301 { public static void main(String[] args) { System.out.println("\"\\\\\"は\"\\\"そのものを表す" ); } } まとめ • • • • • 変数(variable) 型(type) 変数の宣言と初期化 Javaの演算子(operator) 型変換(cast)
© Copyright 2024 ExpyDoc