算術基礎
オペランドと演算子
プログラムにおいて、計算は非常に大切な分野です
これまでも無意識的に、変数や文字列の結合として +演算子 を活用してきました
それ以外でも、変数や定数を合わせた数学的な計算が可能です
プログラムの計算には式を用います
式とは、オペランドと演算子を組み合わせたものです
基礎的な計算には算術演算子を用いてオペランドを指定します
演算子 | 内容
|
---|
+ | 加算
|
- | 減算、負の数
|
* | 乗算
|
/ | 除算
|
% | 剰余
|
+= | 加算して代入
|
-= | 減算して代入
|
*= | 乗算して代入
|
/= | 除算して代入
|
%= | 剰余して代入
|
++ | インクリメント
|
-- | デクリメント
|
計算の優先順位も数学と基本的に同じで、式には任意に括弧 ( ) を用いることもできます
しかし、プログラムの式には必ず評価の出力先が必要です
int var;
var = 10 + 5;
System.out.println((5-3)*5)
式 var = 10 + 5 は評価が整数型変数varに代入されます
また、printlnメソッドでは式を評価してから引数に値が渡されています
このように、式は比較的自由に記述することができます
また、次のような演算も存在します
int var = 5;
var += 10;
この場合は += という演算子は、変数varの現在の値に右オペランドを加算します
つまり var = var + 10; とまったく同じ意味です。しかし、Javaプログラムを熟知している人ならば += を使用するでしょう
プログラミングにおいて、計算は重要な部分なので自由に扱えるようになってください
class test {
public static void main(String args[]) {
int var = 10;
var += 40;
System.out.println("計算の結果は = " + var);
}
}
- 符号などは、何も定数だけに使われるものではありません
プログラミングにおいては変数に用いることもできます
class test {
public static void main(String args[]) {
int var =100;
var = (-var) + (50 * 3);
System.out.println(var);
}
}
(-var) で変数varの内容 100 という正の数を符号を付けることで負の数に変えます
このとき括弧は任意です = と - 演算子が続いたので括弧をつけているだけで、絶対に必要というわけではありません
型の異なる変数式
オペランドに複数の変数が用いられている式の場合、当然型のちがう同士の変数が算術される可能性があります
Java言語は式の中で型のちがうデータの演算が可能な言語です
class test {
public static void main(String args[]) {
int var_int = 10;
float var_float = 10.01f;
System.out.println("結果 = " + (var_int + var_float));
}
}
このプログラムでは出力する時に int型変数var_int と float型変数 var_float を加算していますね
これら二つの変数は型が違います
しかしJava言語には厳密な型変換アルゴリズムが定義されているのでこのような演算が可能なのです
では、実際にprintlnメソッドが出力した値は何の型なのでしょう?
実際に出力されるのは 20.01 です。浮動小数点ですね
ここで予想できた方も多いと思いますが、int型変数がfloat型に変換されています
Javaの型変換アルゴリズムは、サイズの大きい浮動小数点型がもっとも優先されます
一方がdouble型
| No→
|
一方がfloat型
| No→
|
一方がlong型
| No→
|
int型
|
---|
Yes↓ | | Yes↓ | | Yes↓
|
---|
もう一方をdouble型に変換
|
|
もう一方をfloat型に変換
|
|
もう一方をlong型に変換
|
このように、もっとも大きなサイズを確保しているオペランドに合わせて型変換が行われます
このとこを型拡張と呼びます
拡張変換と縮小変換
さらに代入式などの変数の型変換を考えてみましょう
代入式の場合は、式の評価結果が代入する左辺の型に変換されます
このとき左辺の型が右辺よりもサイズが小さくてはいけないということに注意してください
class test {
public static void main(String args[]) {
int var_int = 100;
double var_double = var_int + 0.1234;
System.out.println(var_double);
}
}
上のプログラムの var_double には例によってvar_intがdouble型に変換されvar_doubleに代入されます
これを拡張変換 (widening conversion)と言います
しかし、問題はこの逆の代入を行なった場合です
double var_double = 0.1234;
int var_int = var_double;
浮動小数点型の変数var_doubleを整数型変数var_intに代入しようとしています
しかし、左辺の型が右辺の型よりもサイズが小さいためにコンパイルエラーが発生します
double から int への変換には明示的なキャストが必要です
おそらくこのようなエラーが発生するでしょう
このような変換を行ないたい場合はdouble型変数をint型に型変換(キャスト)する必要があります
型変換は変換する変数名の前に型を指定します
(type) value
浮動小数点を整数型に変換した場合は小数点を切り捨てます
class test {
public static void main(String args[]) {
double var_double = 10.1234;
int var_int = (int)var_double;
System.out.println(var_int);
}
}
また、同じ整数でもint型からbyte型の変換も考えられます
この場合はint型から8ビットまでの数がbyte型変数に変換されて代入されます
class test {
public static void main(String args[]) {
int var_int = 516;
byte var_byte = (byte)var_int;
System.out.println(var_byte);
}
}
この結果 4 が出力されます
これについては「ナゼ?」という方もいると思うので説明しましょう
516をまず2進数に変換します
一番近い桁が512の 10 0000 0000 だと思います
512に4を加算すれば516になります。4を加算して、516を2進数に変換すると 10 0000 0100 になります
この辺はややこしいので計算機を使ったほうが間違いありません
そして、byte型は8ビットなので8桁までしか表現できないです
つまり変換後は 0000 0100 になるという仕組です
このような代入を縮小変換 (narrowing conversion)と言います