入門じゃないJava(2)

こんにちは。

今日も楽しくJavaを見ていきましょう。

前回は整数など(10進数、8進数、16進数とint型、long型)を見ていきました。

creators.hateblo.jp

 

ということは、今日は「浮動小数点数?!」とピンときた方、鋭いですね。

浮動小数点数をちょこっとやった後、もう少し進んでみたいと思います。

でもまずは2の補数表現から見ていきましょう。

 

整数の内部と2の補数表現

前回のどのリテラルも値はビットの並びとして表現されます。

かと言って、それらは好き勝手に並んでいるわけでなく、すべてきちんと規則があります。

整数リテラルはint型long型ですが、それぞれ、表現できる最大と最小があります。

その為、表現できる数は有限という訳です。

int型よりもlong型の方が表せる数の幅は広くなっています。

なぜ、int型とlong型にはそのような差があるかというと、構成ビットが違うからです。

具体的には、int型が32ビットに対して、long型は64ビットです。

ということは、int型のオブジェクトを一つ表す為には0と1が32個用意されていることになります。

そのうち先頭のビットは「符号ビット」として使われます。

もしも先頭のビットが0であれば、その値は0か正の数になるはずで、1であれば負の数になります。

具体的に見てみると、

int型の12という数は、 00000000000000000000000000001100と表現されます。

int型の-12という数は、11111111111111111111111111110010と表現される訳です。

ちなみに、先頭の0が太文字になっていると思いますが、これが符号ビットです。

ここで、↑の12と-12を表しているビットに注目していただきたいのですが、まずは12の方は、10進数の12は2進数では1100になりますので、先頭から1100までの上位ビットは0で埋めたものになります。対して、-12は12の補数(ビットの反転)になっている・・・と言いたいところですが、末尾がおかしいですね。

2の補数表現

負の数は正の数の全ビットを反転させたものに1を加えたビット構成になります。

この作業の名前が「2の補数表現」になります。なお、正の数の全ビットを反転させた(もの)のことを「1の補数」と言います。

浮動小数点数

小数点以下の部分を持つ実数を表すのが浮動小数点型です。

これには、floatとdoubleの2種類があります。

ただし、浮動小数点数の場合、整数型よりも厄介な問題があります。

class DispFloatingLiterals {
    public static void main(String[] args) {
        float  a = 123456789;
        double b = 1234567890123456789L;
        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
}

実行結果

 a = 1.23456782E8
 b = 1.23456789012345677E18

C:\Users\Onwer\Documents>_

 のようになると思います。

※表示されているEは10のべき乗を表す数学的表記。aの1.23456782E8は1.23456782 * 10^8であることを示しています。

なお、1.23456782 * 10^8の1.23456782は仮数、10^8の8を指数と呼び、仮数の桁数が精度を、指数の値が大きさに相当します。

 

見ての通り、変数に入れた値は正確には表現させれていないことがわかります。

これは、浮動小数点型の表現範囲が大きさと精度の両面から制約を受けているためです。

 

浮動小数点接尾語

整数リテラルにはfloat型とdouble型があると書きましたが、基本的にdouble型になります。

しかし、浮動小数点接尾語であるFまたはf(小文字のエフ)をつけるとその浮動小数リテラルはfloat型になります。

double型と明示したいときなどにはDまたはdを指定します。

たとえば、12.0、12.0Dはdouble型ですが、12.0Fはfloat型と解釈されます。

 

数学的表記と省略

 実は指数を付けた数学的表記や整数部、小数部の省略が可能です。

ただし、いくつかの規則等もありますので、確認しながら見ていきましょう。

class DispSomeFloating {
    public static void main(String[] args) {
        
        System.out.println("1.23E4   =   " + 1.23E4); //1.23 * 10^4
        System.out.println("80.0E-5  =   " + 80.0E-5);//80.0 * 10^-5

        System.out.println(".5       =   " + .5);     //0.5
        System.out.println("5.       =   " + 5.);     //10.0
        System.out.println(".5f      =   " + .5f);    //floatの0.5
        System.out.println("5D       =   " + 5D);     //5.0
    }
}

実行結果

1.23E4   = 12300.0
1.23E4 = 12300.0
80.0E-5 = 8.0E-4
.5 = 0.5
5. = 5.0
.5f = 0.5
5D = 5.0
C:\Users\Onwer\Documents>_

 今日はここまでにしましょう。

次回はもう少し踏み込んだ内容にしていきたいと思います。

では次回もお楽しみに!

参考文献

柴田 望洋 (2016) .『新・明解Java入門』150-155