アルゴリズムとプログラミング

アルゴリズムとプログラミング
(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)