JAVA/연산자(Operator)

[JAVA] 산술 연산자

prize1209 2021. 6. 7. 14:13

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