1. 사칙연산자
곱셈(*), 나눗셈(/), 나머지(%) 연산자가 덧셈(+), 뺄셈(-) 연산자보다 우선순위가 높으므로 먼저 처리된다.
그리고 피연산자가 정수형인 경우, 나누는 수로 0을 사용할 수 없다. 만일 0으로 나누면 에러가 발생한다.
예5)
public class OperatorEx5 {
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);
}
}
예7)
public class OperatorEx7 {
public static void main(String[] args) {
byte a =10;
byte b =30;
byte c = (byte)(a*b);
System.out.println(c);
}
}
10*30 의 결과는 300이지만 형변환에서 배운 것처럼 큰 자료형에서 작은 자료형으로 변환하면 데이터 손실이 발생하므로 값이 바뀔 수 있다. 300은 byte 형의 범위를 넘기 때문에 byte 형으로 변환하면 데이터 손실이 발생하여 44가 byte형 변수 c에 저장된다.
예8)
public class OperatorEx8 {
public static void main(String[] args) {
int a = 1_000_000;
int b = 2_000_000;
long c = a*b;
System.out.println(c);
}
}
a*b의 값을 담는 c의 자료형이 long타입이라서 충분하기에 2000000000000이 출력될 것 같지만 아니다.
int 타입과 int 타입의 연산 결과는 int타입이기 때문이다. a*b의 결과 -1454759936 이미 int타입이므로 long 형으로 자동 형변환되어도 값은 변하지 않는다.
올바른 결과를 얻으려면 a또는 b의 값을 long으로 형변환해줘야 한다.
public class OperatorEx8 {
public static void main(String[] args) {
int a = 1_000_000;
int b = 2_000_000;
long c = (long)a*b;
System.out.println(c);
}
}
예11)
public class OperatorEx11 {
public static void main(String[] args) {
char a = 'a';
char d = 'd';
char zero = '0';
char two = '2';
System.out.printf("'%c'-'%c'=%d%n", d,a, d-a); //3
System.out.printf("'%c'-'%c'=%d%n", two,zero, two-zero); //3
System.out.printf("'%c=%d%n", a, (int)a);
System.out.printf("'%c=%d%n", d, (int)d);
System.out.printf("'%c=%d%n", zero, (int)zero);
System.out.printf("'%c=%d%n", two, (int)two);
}
}
사칙연산의 피연산자로 문자도 가능하다. 문자는 유니코드(부호없는 정수)로 바뀌어 저장되므로 문자간의 사칙연산은 정수간의 연산과 동일하다.
'2'-'0'->50-48->2
문자 '2'를 숫자로 변환하려면 '0'을 빼주면 된다.
'0'~'9'까지의 문자가 연속적으로 배치되어 있다. 그래서 해당 문자에서 '0'을 빼주면 숫자로 변환된다.
예12)
public class OperatorEx12 {
public static void main(String[] args) {
char c1 = 'a'; //c1에는 코드값 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변수 c3에 담기위해서는 char형으로의 형변환이 필요.
c2++;
c2++; // c2의 값 두번 증가시킴 . 97이 두번 증가되어 99->'c'
System.out.println("i="+i);
System.out.println("c2="+c2);
System.out.println("c3="+c3); // 98의 문자 b 출력
}
}
예13)
public class OperatorEx13 {
public static void main(String[] args) {
char c1 = 'a';
// char c2 = c1+1; 컴파일 에러 발생
char c2 = 'a'+1;
System.out.println(c2);
}
}
덧셈 연산자 같은 이항 연산자는 int보다 작은 타입의 피연산자를 int로 자동 형변환한다고 배웠는데, 왜 아래처럼 형변환해주지 않아도 되는 걸까?
char c2 = (char)('a'+1);
'a'+1 이 리터럴 간의 연산이기 때문이다. 상수 또는 리터럴 간의 연산은 실행 과정 동안 변하는 값이 아니기 때문에 컴파일 시 컴파일러가 계산해서 그 결과로 대체한다.
char c2 = c1+1;
은 수식에 변수가 들어있어 컴파일러가 미리 계산을 할 수 없어서 형변환을 해줘야한다.
->char c2 = (char)(c1+1);
예14)
public class OperatorEx14 {
public static void main(String[] args) {
char c = 'a'; //
for (int i = 0; i < 26; i++) {
System.out.print(c++); // a부터 26개의 문자 출력
}
System.out.println();
c = 'A';
for (int i = 0; i < 26; i++) {
System.out.print(c++); // 'A'부터 26개의 문자 출력
}
System.out.println();
c = '0';
for (int i = 0; i < 10; i++) {
System.out.print(c++); // 0부터 10개의 문자 출력
}
System.out.println();
}
}
문자 코드값은 10진수로 a=97, b= 98, c= 99,....z=122이다.
문자 A=65, B=66...Z=90이다.
문자 0은 48이다.
예15)
public class OperatorEx15 {
public static void main(String[] args) {
char lowercase = 'a';
char UpperCase = (char)(lowercase-32);
System.out.println(UpperCase);
}
}
대문자를 소문자로, 소문자를 대문자로 바꿀 수 있다.
소문자a의 코드값은 97, 대문자 A의 코드값은 65. 즉 32 차이가 난다.
따라서 -32 해주면 대문자 코드가 나온다.
반대로 대문자 코드+32 해주면 소문자가 나온다.
예16-18)
public class OperatorEx16 {
public static void main(String[] args) {
float pi = 3.141592f;
float shortpi = (int) (pi * 1000) / 1000f;
System.out.println(shortpi);
double pi2 = 3.141592;
double shortpi2 = (int) (pi2 * 1000 + 0.5) / 1000.0;
System.out.println(shortpi2);
double pi3 = 3.141592;
double shortpi3 = (int) (Math.round(pi3 * 1000)) / 1000.0;
System.out.println(shortpi3);
}
}
Math.round 함수는 소수 첫 번째 자리를 반올림하여 정수 값을 리턴한다.
2. 나머지 연산자(%)
왼쪽의 피연산자를 오른쪽 피연산자로 나누고 난 나머지 값을 결과로 리턴한다. 오른쪽 피연산자로 0을 사용할 수 없다.
예19)
public class OperatorEx19 {
public static void main(String[] args) {
int x =10;
int y = 8;
System.out.printf("%d를 %d로 나누면, %n" , x, y);
System.out.printf("몫은 %d 이고, 나머지는 %d 입니다", x/y, x%y);
}
}
예20)
public class OperatorEx20 {
public static void main(String[] args) {
System.out.println(-10%8);
System.out.println(10%-8);
System.out.println(-10%-8);
}
}
나머지 연산자(%)는 음수도 허용한다. 그러나 부호는 무시되므로 결과는 음수의 절대값으로 나눈 나머지와 같다.
피연산자의 부호를 모두 무시하고, 나머지 연산을 한 결과에 왼쪽 피연산자(나눠지는 수)의 부호를 붙이면 된다.
'JAVA > 연산자(Operator)' 카테고리의 다른 글
[JAVA] charAt() (0) | 2021.06.08 |
---|---|
[JAVA] 논리 연산자 (0) | 2021.06.08 |
[JAVA] 비교 연산자 (0) | 2021.06.08 |
[JAVA] 증감 연산자/부호 연산자 (0) | 2021.06.06 |
[JAVA] 연산자(operator) (0) | 2021.06.06 |