420 likes | 613 Views
アルゴリズムとプログラミング (Algorithms and Programming). 変数 (variable) とは 変数の 型 (type) 変数の 宣言 と初期化 変数への値の 代入 型変換 (cast) Java の 演算子 (operator) ( 補足 ) 文字型の取り扱い. 第 2 回: Java の変数と演算子. 講義資料等:. http://www.pe.titech.ac.jp/~watanabe/lecture/ap/index-j.html. Java 開発環境の準備. Java のインストール
E N D
アルゴリズムとプログラミング(Algorithms and Programming) • 変数(variable)とは • 変数の型(type) • 変数の宣言と初期化 • 変数への値の代入 • 型変換(cast) • Javaの演算子(operator) • (補足)文字型の取り扱い 第2回:Javaの変数と演算子 講義資料等: 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):変数に格納する値の種類が規定される (ビット数とその解釈)
変数の宣言=メモリ領域の確保 例)byte型の変数bを宣言する 記法: byte b; メモリ アドレス 8bit分のデータ を格納する領域 0000 34 コンパイラが、 変数bの値を格納する メモリ領域を確保する (コンパイラの仕事. プログラマは宣言するだけ.) 0001 AF 0002 21 0003 D1 0004 04 0005 7F FFFE 00 FFFF BB
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ●10進数で0~255 ●byte型は符号付整数なので, 正負半分ずつにふり分けて -128~127 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 最上位ビットが1なら負数 byte型(8bit)の値の範囲 表現できる値の個数は? →28 (=256)個 負数の求め方→2の補数表現
1 1 0 0 1 1 1 1 0 0 1 1 0 1 1 0 1 1 0 1 1 1 0 1 -1の2進数表現を求める • 1の2の補数をとる 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型も同様
23+22+ 20 + 2-1 + 2-4 2進数の小数表記 23 22 21 20 2-1 2-2 2-3 2-4 1 1 0 1 1 0 0 1 二進数 十進数 0.10002-1 = 0.5 0.01002-2 = 0.25 0.00102-3 = 0.125 0.00012-4 = 0.0625
表記の例: 3.14 6.02E+23 (→6.02×1023) 浮動小数点(floating point) (仮数部)×2(指数部)の形に変換し, (仮数)と(指数)をビット列としてメモリに保存 浮動小数点数の宣言と値の代入: double x, y ; float z = 2.05 ;
float型のビット構成(IEEE754規格32bit浮動小数点数)float型のビット構成(IEEE754規格32bit浮動小数点数) ビットレイアウト 低位桁 高位桁 222 263 24 23 21 20 符号部S(1bit) 指数部e(8bit) 仮数部k(23bit) 指数部の2進数表現 float値への変換 ... 1000 0011+4乗 1000 0010+3乗 1000 0001+2乗 1000 0000+1乗 0111 11110乗 0111 1110-1乗 0111 1101-2乗 0111 1100-3乗 ... 指数 1. × 2 符号S 仮数k 2進数表記 0: + 1: - 127(10) 8bit指数部の値から 127を引いた値が 実際の指数を表す 0は、符号部、仮数部、指数部=0で表現 無限大、無限小の表現も定義されている
float値(32bit)のビットレイアウトを表示するJavaプログラム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プログラム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浮動小数点数)double型のビット構成(IEEE754規格64bit浮動小数点数) ビットレイアウト 低位桁 高位桁 263 251 24 23 21 20 符号部S(1bit) 指数部e(11bit) 仮数部k(52bit) double値への変換 指数 符号 1. 仮数 × 2 2進数表記 0: + 1: -
宣言(型と変数名を決める) 値の代入(=は代入演算子) 意味は上と同じ int i = 0 ; セミコロンは文の終わりを表す. 忘れると文が次の行まで続いて いることになってしまうので注意! 変数の宣言と値の代入 int i ; i = 0 ; 0 = i ;
識別子の命名規則 変数名,クラス名など • 使える文字は半角文字の英字・数字・アンダースコア「_」に限定(例外は多いが避けた方が無難) • 半角英字の大文字・小文字は区別される • 数字で始まる識別子は認めない • キーワード(keyword)と呼ばれるJavaの予約語と、true・false・nullの3単語は使用できない。(他の語句と組み合わせれば可) • 長さに制限はない
int型の変数aを宣言する int型の変数bを宣言し、値10を代入する この表記法に関しては後の講義で サンプルプログラム(宣言と代入) ファイル名:Sample1401.java class Sample1401 { public static void main(String[] args) { int a; 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
intの最大値 実行結果: -2147483648 クイズ: 下記プログラムの実行結果は? ファイル: AP0201.java class AP0201 { public static void main(String[] args) { int i = 2147483647 ; i = i + 1 ; System.out.println(i); } } 教訓:最大値に留意して変数の型を選択せよ!
数値リテラル(定数)の表記法 整数リテラル 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がやっていることは意外と手が込んでいる!!
右辺の型がintと判断されるので、演算はint型で実施される。86400000000 はオーバーフローし、予期しない値がlongに拡張型変換されて 変数 i に代入される。 注意! 下記プログラムは意図した動作をしない! long i = 24 * 60 * 60 * 1000 * 1000 ; (マイクロ秒単位の1日の長さ) 代入したい数値は 86400000000 である。int値の範囲からは逸脱しているがlong値の範囲内には入っている。一見正しそうだが。
演算子と優先順位 優先順位 高い 低い (同一グループ内の優先順位は同じ)
多重代入式の動作 (右から左へ) 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++ (a++)をaの中身の値で置き換える (1)(a++)の値としてaの値を採用する (2)変数aの値に1を加算する 評価 加算 前置 ++a (1)変数aの値に1を加算する (2)加算した結果を(++a)の値として採用する 加算 評価 値の評価と加算の順序が異なる!!
インクリメント演算子と代入文 int tmp = a ; a = a + 1 ; b = tmp ; b = a++ ; (1)(a++)の値としてaの値を採用する (2)変数aの値に1を加算する (3)(1)で採用した(a++)の値をbに代入する 評価 インクリメント 演算子の実行 加算 代入演算子の 実行 b = ++a ; (1)変数aの値に1を加算する (2)加算した結果を(++a)の値とする (3)(2)で確定した値をbに代入する 加算 a = a+1; b = a ; 評価 実行後のaの値は同じだが、bの値は異なる!!
++、ーー演算子を含む式の実行(オペランドの値の決定と演算順序に関する注意)++、ーー演算子を含む式の実行(オペランドの値の決定と演算順序に関する注意) a=2; b = --a * a ; // b=1 a=2; b = a-- + --a ; // b=2 a=2; b = a * --a ; // b=2 a=2; b = a + --a * a; // b=3 a=2; b = a + a * --a; // b=4 a=2; b = --a + a * a ; // 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 ) ;
桁あふれ 型が異なる変数の代入 int a = 0 ; long b = 0; b = a ; a = b ; 型の違う変数の代入 OK 値を比較しているの ではなく、型の大きさ だけで判断 エラー!! 代入 0 0 0 0 0 0 0 0 (byte) (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.5 * i ; d = i – d ; d = 0 d = 0.5*(double)1=0.5 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クラス等,後述
解答例:AP0301.java class AP0301 { public static void main(String[] args) { System.out.println("\"\\\\\"は\"\\\"そのものを表す" ); } } クイズ: 下の四角で囲った文を出力するJavaプログラムを書きなさい。 ”\\”は”\”そのものを表す (“や\は半角文字とする)
まとめ • 変数(variable) • 型(type) • 変数の宣言と初期化 • Javaの演算子(operator) • 型変換(cast)