基本データ型

コンピュータは,本来 compute(計算)する機械であり,機械語のレベルで数 値データを扱えるようにできている.Java言語が基本データ型として用意して いる数値データは以下のとおりである.
サイズ 定数の例
byte 符号付き整数 8ビット 100
short 符号付き整数 16ビット 1000
char 符号なし整数 16ビット 'c'
int 符号付き整数 32ビット -1000000
long 符号付き整数 64ビット 100000000
float 浮動小数点数 32ビット -3.45e+4
double 浮動小数点数 64ビット 4.195e-300
byte, short, int, long は整数データを表現するためのものだが,数学でい う整数と違って,限られた範囲の整数しか表現できない.表現できる範囲は, ビット数(2進数で何桁分の記憶領域を使うか)によって決まる.たとえば,16 ビットで表現される short 型の場合は,-215 〜 215 -1 の範囲を表現できる.

char は文字コードを表すもの.UNICODE と呼ばれる世界中の文字を16ビット で表すことを目指したコード系を用いて文字を整数に変換する.プログラム中 ではchar型の定数は,「'a'」のように表す.ASCII文字についてはASCIIの8ビットのコード(man ascii で見られる)と一致している(例 'a' -> 97).

float, doubleは実数データを表すのに用いる.浮動小数点数というのは, 実数を2進法で表した時の桁数を表すビット(指数部)とその時の上位の桁 を表すビット(仮数部)によって表現する. -3.45e+4 という定数は, -3.45 に 10の4乗(=10000)を掛けた数. すなわち-34500を表す.


この中で,よく使う型は int と double で他の型はメモリを節約する必要が ある場合,低レベルの入出力をおこなう場合しか使わない.それらの必要がな ければ,他の型はあまり気にしなくて良い.
数を扱うために,さまざまな演算子が用意されている.この演算子を組み合わ せることにより,数式と同じように演算を自然な式の形で表現することができ る.このように,演算の対象とする式の間に置かれる演算子を中置演算子 (infix operatr)と言う. Javaの演算子の主なものを以下にあげる.
優先順位 演算子 扱うデータ型 結合規則 演算の内容
1 + 数値 単項演算子のプラス
1 - 数値 単項演算子のマイナス
2 * 数値 乗算
2 / 数値 除算
2 % 数値 剰余
3 + 数値 加算
3 - 数値 減算
5 < 数値 より小さい
5 <= 数値 以下
5 > 数値 より大きい
5 >= 数値 以上
6 == 基本データ型 等しい
6 != 基本データ型 等しくない
13 = 左辺は変数 代入
以前,出てきた代入も実は演算子となっている.

優先順位, 結合規則は, 複数の演算子を含む式をどう解釈するかを表す. たとえば,

1 + 2 * 3
は, '*'の優先順位が'+'よりも高いので, 2 と 3の乗算の実行後に1との加算 をおこなうということになる. これを1と2の加算の実行後に3と乗算するよう に変更するには,
(1+2)*3
のように書けば良い. 式を自然に書けない言語もある.たとえば,Lispという言語では (1+2)を表 現するのに,(+ 1 2) という前置記法を用い,Forth という言語では1 2 + と いう逆ポーランド記法を用いる.それぞれの方法にメリットがあり熱狂的なファ ンも多いが,主流となる言語は中置演算子を用いてきた.

実数は整数と濃度が違うとい う集合論の理論でもあきらかなように,すべての実数が2進数で表せるわけで はない.したがって,計算機で実数を扱う場合は何らかの近似を行う.そのた め,実数演算をおこなう場合は誤差を無視することができない.たとえば, (1.0/3.0)*3.0 は誤差が入るため,1.0とは違う.


整数は桁数が限られているため,範囲外の数を扱おうとするとおかしなことが起 きる.
class Pow10{
  public static void main(String[] args){
    // java Pow10 ???
    // で起動した 「???」の部分の文字列 args[0] を
    // 整数値に変換して,nに入れる.
    int n=Integer.parseInt(args[0]);
    int i,v=1;
    // i 回繰り返す
    for(i=0;i< n;i++){
      // vを10倍する.
      v*=10;
    }
    System.out.println("10の"+i+"乗は"+v+"です");
  }
}

dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 0
10の0乗は1です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 9
10の9乗は1000000000です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 10
10の10乗は1410065408です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 11
10の11乗は1215752192です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 12
10の12乗は-727379968です
のように整数の場合は,桁あふれを起こしても,エラーを出さずに間違った値が 入ってしまうので注意が必要になる.32ビット(2進数で32桁)しか表せない int 型 の代わりに64ビット(2進数で64桁)表せる long 型を使って,
class Pow10{
  public static void main(String[] args){
    // java Pow10 ???
    // で起動した 「???」の部分の文字列 args[0] を
    // 整数値に変換して,nに入れる.
    int n=Integer.parseInt(args[0]);
    int i;
    long v=1;
    // i 回繰り返す
    for(i=0;i< n;i++){
      // vを10倍する.
      v*=10;
    }
    System.out.println("10の"+i+"乗は"+v+"です");
  }
}
と書くと,
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 12
10の12乗は1000000000000です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 18
10の18乗は1000000000000000000です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10 19
10の19乗は-8446744073709551616です
と正しい結果が得られるが,それでもまだ制限はある.更に,doubleを使って,
class Pow10Double{
  public static void main(String[] args){
    // java Pow10 ???
    // で起動した 「???」の部分の文字列 args[0] を
    // 整数値に変換して,nに入れる.
    int n=Integer.parseInt(args[0]);
    int i;
    double v=1;
    // i 回繰り返す
    for(i=0;i< n;i++){
      // vを10倍する.
      v*=10;
    }
    System.out.println("10の"+i+"乗は"+v+"です");
  }
}
とすると,表現可能な範囲は
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10Double 20
10の20乗は1.0E20です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10Double 308
10の308乗は9.999999999999998E307です
dell.tanaka.ecc.u-tokyo.ac.jp% java Pow10Double 309
10の309乗はInfinityです
と広がるが,限界があることには変わりがない.

実数と整数との間の型変換

実数の値を整数型の変数に代入したり,整数値を実数型の変数に代入したり したいことがある.このような際に,型変換をおこなう必要がある.型変換に は,暗黙(implicit)の型変換と明示的(explicit)な型変換の2種類がある.
明示的な型変換
Java言語には「(型の名前)式」とすると,式の値を計算した上で指定し た型に変換可能な場合は変換するという構文(キャスト演算子)が用意されてい る.
暗黙の型変換
整数値を実数型の変数に代入する場合などは,明示的に指定しなくても 自動的に変換をおこなってくれる.これを暗黙の型変換と呼ぶ.
この例を見てみる.
class ConvTest{
  public static void main(String[] args){
    long i=0,j;
    double f=-1.9,g;
    // j=f; // この行を残すとコンパイルエラーが出る
    j=(int)f; // 実数から整数への変換
    g=i;      // 整数から実数への暗黙の変換
    g=(double)i; // 整数から実数への明示的な変換 
    System.out.println("j="+j+",g="+g); // 表示
  }
}
実行してみると,
dell.tanaka.ecc.u-tokyo.ac.jp% java ConvTest
j=-1,g=0.0
となる.実数から整数への変換としてまず思いつくのが四捨五入だが,Java言 語の実数から整数への変換は四捨五入ではない(実は0の方向への丸め)とわか る.四捨五入(というか一番近い整数値に変換)をおこなたい場合は,Mathクラスのrintメソッドを使って,
class ConvTest{
  public static void main(String[] args){
    long i=0,j;
    double f=-1.9,g;
    // j=f; // この行を残すとコンパイルエラーが出る
    j=(int)Math.rint(f); // 一番近い整数値に変換
    g=i;      // 整数から実数への暗黙の変換
    g=(double)i; // 整数から実数への明示的な変換 
    System.out.println("j="+j+",g="+g); // 表示
  }
}
とする必要がある.
その他の制御文