산술 연산자
사칙 연산자는 덧셈(+) 뺄셈(-) 곱셈(*) 나눗셈(/)이다.
주의할 점은 나누기 연산자를 할 때 피연산자가 둘 다 int타입인 경우 소수점을 저장하지 못하므로 정수만 남고 소수점 이하는 버려지며, 반올림도 발생하지 않는다.
public class OperatorEx05 {
public static void main(String[] args) {
int a = 10;
int b = 4;
System.out.printf("%d + %d = %d%n", a, b, a + b);
System.out.printf("%d - %d = %d%n", a, b, a - b);
System.out.printf("%d * %d = %d%n", a, b, a * b);
System.out.printf("%d / %d = %d%n", a, b, a / b);
System.out.printf("%d / %f = %f%n", a, (float) b, a / (float) b);
}
}
10 + 4 = 14
10 - 4 = 6
10 * 4 = 40
10 / 4 = 2
10 / 4.000000 = 2.500000
x | y | x/y | x%y |
유한수 | +-0.0 | +-Infinity | NaN |
유한수 | +-Infinity | +-0.0 | x |
+-0.0 | +-0.0 | NaN | NaN |
+-Infinity | 유한수 | +-Infinity | NaN |
+-Infinity | +-Infinity | NaN | NaN |
피연산자가 유한수가 아닐 경우 연산 결과이다.
기본적으로 올바른 연산 결과를 얻기 위해서는 수치가 큰 쪽으로 형 변환하며, 만약 크기가 작다면 int형으로 자동으로 변환되어 계산된다.
또한 기존에 변수를 byte로 정의하더라도, 산술 연산자로 연산을 하면 int로 자동 형 변환(rype conversion, casting)이 되어 계산이 된다.
그리고 큰 자료형에서 작은 자료형으로 변환하거나 논리형이 다르면 데이터 손실이 발생하므로
같은 논리형의 동일한 크기의 자료 혹은 같은 논리형의 큰 크기의 자료형으로 변경해야 데이터 손실이 적거나 없다.
또한 자료형의 범위를 넘어가면 오버플로우나 언더플로우가 발생한다.
그리고 일반적인 사칙연산과 다르게 자바 프로그램의 사칙연산은 숫자뿐 아니라 문자로도 사칙연산이 가능하다.
이는 문자가 실제로 문자 그대로 저장되는 것이 아니라 해당 문자의 유니코드로 바뀌어 저장되기 때문이다.
만약 문자에 해당하는 숫자를 보고 싶다면 ch타입의 문자를 int형태로 형 변환하면 된다.
문자 | 코드 | 문자 | 코드 | 문자 | 코드 |
0 | 48 | A | 65 | a | 97 |
1 | 49 | B | 66 | b | 98 |
2 | 50 | C | 67 | c | 99 |
3 | 51 | D | 68 | d | 100 |
4 | 52 | E | 69 | e | 101 |
5 | 53 | ... | ... | ... | ... |
6 | 54 | X | 88 | x | 120 |
7 | 55 | Y | 89 | y | 121 |
8 | 56 | Z | 90 | z | 122 |
숫자랑 문자는 연속적으로 되어있는데 특이하게 영문의 경우 대문자 소문자의 시작 코드 사이에 다른 문자가 있으니 문자 형태로 계산할 시 조심하자. 소문자 a에서 대문자 A를 빼면 32의 값이 차이가 나며 대문자, 소문자, 숫자의 시작 코드와 소문자와 대문자의 코드의 차가 32라는것을 알아두면 좋다.
public class OperatorEx12 {
public static void main(String[] args) {
char c1 = 'a'; // c1에는 문자 'a'의 코드값인 97이 저장된다.
char c2 = c1; // c1에 저장되어 있는 값이 c2에 저장된다.
char c3 = ' '; // c3를 공백으로 초기화 한다.
int i = c1 + 1; // 'a'+1 > 97+1 > 98
c3 = (char)(c1 + 1); // c1 + 1의 형태가 int 이므로 char로 변환
c2++;
c2++;
System.out.println("i=" + i);
System.out.println("c2=" + c2);
System.out.println("c3=" + c3);
}
}
i=98
c2=c
c3=b
c1+1은 int로 바꾼'a'+1=97+1=98이 되어 저장된다,
c2는 형변환 없이 c2에 에 저장된 값에 +2가 되므로 (char)99='c'가되는 것이다.
보통 일부러 뻔한 리터럴 연산을 풀어 쓸 필요가없이 답을 적으면 되지만, 가독성 때문에 그렇게 하는 경우가있다.
예를들어 86400이라는 숫자는 무엇을 의미하는지 선뜻 이해하기 어려울 수 있지만 이것을 60*60*24로 쓰면 초, 분, 시 를곱한값으로 이해하기 쉬워진다. 이렇게 써도 컴파일러에 의해 미리 계산되기 때문에 성능 차이는없다.
public class OperatorEx17 {
public static void main(String[] args) {
double pi = 3.141592;
double shortPi = (int)(pi * 1000 + 0.5) / 1000.0;
System.out.println(shortPi);
}
3.142
나눗셈의 경우 주의할 점이 있는데 double타입으로 정의한 변수를 나눈다 하더라도 위의 경우 int형으로 계산이 되며 나머지는 버려진다는 점이다. 반면에 이런 특징을 이용해서 식으로 반올림을 할 수 있다.