Java入門|異なる型どうしで演算する

型の違いを意識できるようになると、Javaの計算結果はぐっと正確に読み解けるようになります。

Javaでは、数値を使った計算を書くことがとても多いですが、そのときに見落としやすいのが型の違いです。見た目にはどちらも数字でも、int 型の整数なのか、double 型の小数なのかによって、計算のされ方や結果の型が変わることがあります。

これまでに見てきたように、Javaは型をしっかり区別して扱う言語です。そのため、演算子を使って計算するときも、ただ数字を並べて計算しているのではなく、どの型の値どうしを演算しているかがとても大切になります。ここが理解できるようになると、「なぜこの結果になったのか」がかなりはっきり見えるようになります。

特に、異なる型どうしで演算するときには、Javaが自動的に一方の型を変換してから計算を行います。一方で、同じ型どうしの演算では、その型のまま計算されるため、思っていた結果と違う値になることもあります。とくに整数どうしの割り算は、初心者がとてもつまずきやすいポイントです。

ここでは、まず異なる型どうしで演算する場合のしくみを見て、そのあとで同じ型どうしの演算で起こりやすい注意点を、サンプルプログラムと図を交えながら丁寧に見ていきましょう。

異なる型どうしで演算する

まずは、異なる型どうしの計算から見ていきましょう。Javaでは、四則演算などの演算子に異なる型のオペランドを指定した場合、一般的に一方のオペランドを大きなサイズの型に変換してから演算するというきまりがあります。

ファイル名:Sample10.java

class Sample10
{
    public static void main(String[] args)
    {
        int count = 3;
        double price = 2.5;

        // 個数と単価をかけて合計金額を求める
        System.out.println("商品を " + count + " 個買います。");
        System.out.println("合計金額は " + (count * price) + " 円です。");
    }
}

実行結果を確認しよう

このプログラムを実行すると、次のようになります。

商品を 3 個買います。
合計金額は 7.5 円です。

ここでは、int 型の count と、double 型の price を掛け算しています。count は整数の 3、price は小数を含む 2.5 です。この2つは型が異なりますが、Javaではこのまま計算できます。

その理由は、int 型の 3 が double 型の 3.0 に変換されてから計算されるからです。つまり、内部では次のようなイメージで処理されています。

3.0 * 2.5

その結果、得られる値も double 型となり、7.5 になります。

なぜ大きい型にそろえるのか

Javaが異なる型どうしの演算をするときに、大きい型へそろえるのは、情報を失わないようにするためです。

今回の例では、

  • count は int 型
  • price は double 型

でした。double 型は小数を扱えるので、int 型の値も無理なく表せます。そこで、count の値を double 型に変換してから計算するわけです。

もし逆に、double 型の値を int 型に合わせてしまうと、小数部分が失われてしまう可能性があります。たとえば 2.5 を 2 にして計算してしまったら、正しい結果になりませんよね。Javaはそうならないように、より大きい型へ合わせて演算します。

異なる型の演算の流れを表で見てみよう

今回の例を表にすると、次のようになります。

元の型演算前の扱い
count = 3intdouble の 3.0 に変換される
price = 2.5doubleそのまま使われる

そして計算後は、

結果の型結果の値
count * pricedouble7.5

となります。

つまり、異なる型どうしの演算では、大きい型にそろえて計算し、結果もその型になると考えるとわかりやすいです。

この図では、int 型の 3 が double 型の 3.0 に変換され、そのあとで double 型の 2.5 と掛け算される流れを示しています。結果も double 型の 7.5 になっています。

ここで押さえておきたいのは、型が異なるまま無理に計算するのではなく、Javaが先に型をそろえてから演算しているという点です。

同じ型どうしで演算する

では次に、同じ型どうしで演算する場合を見てみましょう。同じ型どうしならわかりやすそうですが、ここには注意したいポイントがあります。特に、整数どうしの割り算では思ったような結果にならないことがあります。

ファイル名:Sample11.java

class Sample11
{
    public static void main(String[] args)
    {
        int total = 7;
        int people = 2;

        // 7を2で割った結果をdouble型へ代入する
        double result = total / people;

        System.out.println("7を2で割った結果は " + result + " です。");
    }
}

実行結果を見てみよう

このプログラムを実行すると、次のようになります。

7を2で割った結果は 3.0 です。

ここで「3.5 になるのでは」と思ったかもしれません。けれど、実際には 3.0 が表示されます。

なぜ 3.5 ではなく 3.0 になるのか

ポイントは、割り算をしている total と people が、どちらも int 型だということです。

Javaでは、int 型どうしの割り算は int 型として計算されます。
つまり、

7 / 2

は、整数の割り算として扱われるため、結果は 3 になります。小数部分の 0.5 は切り捨てられます。

そのあと、その結果の 3 が double 型の変数 result に代入されるので、最終的には 3.0 になるわけです。

ここで大切なのは、double 型の変数に入れているからといって、割り算そのものが double 型で行われるわけではないということです。まず int 型どうしで計算され、その結果が代入されているのです。

同じ型どうしの演算の流れを表で整理しよう

今回の例を表にすると、次のようになります。

total = 7int
people = 2int

そして演算はこうなります。

計算時の型計算結果
total / peopleint3

その後で、

代入先代入される値
double result3.0

となります。

つまり、計算の時点で int 型の結果 3 が確定しているので、あとから double に入れても 3.5 にはなりません。

この図では、int 型の 7 と int 型の 2 が割り算され、その結果が int 型の 3 になる流れを示しています。そのあとで、その 3 が double 型へ代入されるので、表示される値は 3.0 になります。

この図からわかるように、計算に使うオペランドの型が結果を左右することがとても大切です。

3.5 のような結果を得るにはどうすればよいか

では、7 ÷ 2 の結果を 3.5 としたいときはどうすればよいのでしょうか。

そのためには、少なくとも一方のオペランドを double 型に変換してから割り算を行う必要があります。たとえば、キャスト演算子を使って次のように書きます。

double result = (double)total / (double)people;

このように書くと、割り算の前に total と people がどちらも double 型に変換されるため、計算は小数を含む double 型の割り算になります。

修正後のプログラムを見てみよう

ファイル名:Sample11.java

class Sample11
{
    public static void main(String[] args)
    {
        int total = 7;
        int people = 2;

        // キャストしてdouble型として割り算する
        double result = (double)total / (double)people;

        System.out.println("7を2で割った結果は " + result + " です。");
    }
}

このプログラムを実行すると、次のようになります。

7を2で割った結果は 3.5 です。

今度は期待どおりの結果になりました。

なぜキャストすると結果が変わるのか

キャストによって total と people が double 型になるため、Javaは次のような計算として扱います。

7.0 / 2.0

この場合、結果は double 型の 3.5 になります。

ここでのポイントは、代入先の型ではなく、演算に参加しているオペランドの型が重要だということです。
たとえ結果を double 型の変数に入れるとしても、演算の時点で int 型どうしなら整数の割り算になってしまいます。

片方だけを double 型にしてもよい

なお、両方を double 型に変換しなくても、片方だけ double 型にすれば大丈夫です。異なる型どうしの演算では、大きい型にそろえられるからです。

たとえば、次のような書き方でもかまいません。

double result = (double)total / people;

または、

double result = total / (double)people;

どちらでも、片方が double 型になっているので、もう片方も double 型へそろえられて計算されます。

よくあるつまずきポイント

この内容でとくに気をつけたい点を整理しておきます。

つまずきやすい点実際のポイント
double 型の変数に代入すれば小数になると思ってしまう演算の時点の型が重要
7 / 2 は 3.5 になると思ってしまうint 型どうしなら結果は 3
キャストは代入のときだけ使うと思ってしまう演算の前に使うことが大切な場面がある

特に、どの型で計算しているのかを意識することがとても大切です。

異なる型どうしの演算と同じ型どうしの演算の違い

最後に、今回の内容を比較しながら整理してみましょう。

パターン計算のされ方結果
異なる型どうしint × double大きい型にそろえて計算double 型の結果
同じ型どうしint / intその型のまま計算int 型の結果
int / int を小数で出したい(double)int / intdouble 型に変換してから計算double 型の結果

この表からもわかるように、Javaの演算では、型が結果に大きく影響します。

型を意識すると計算の意味がよくわかる

数値の計算というと、どうしても数字そのものばかりに目が向きがちですが、Javaではその数字がどの型で扱われているかがとても重要です。異なる型どうしなら大きい型にそろえられますし、同じ型どうしならその型のまま計算されます。

特に割り算では、この違いが結果にはっきり表れます。だからこそ、式を見るときには「この値は int かな、double かな」と考える習慣をつけておくと、思わぬミスを防ぎやすくなります。

型を意識して演算を読む力がついてくると、Javaのコードがただの数字の並びではなく、きちんとルールに従って動いていることが見えてきます。ここがわかってくると、プログラムを書くときの安心感もぐっと増していきます。