연산자

이동주·2025년 3월 1일

JAVA

목록 보기
7/30

부호/증감 연산자

부호 연산자

-> +,- : 더하기, 빼기

증감 연산자

-> ++, -- : 값에 1을 더하거나 빼는 연산자
-> 단독으로 쓰일 때는 증감 연산이 그대로 일어나지만, 다른 연산식과 함께 사용 될때에는 연산자의 위치에 따라 차이가 난다

전위형 증감 연산자

-> 현재 위치에서 증감 연산이 이루어지는 연산자 (선 계산, 후 대입)

++x : x 값에 1을 더하고 대입
--x : x 값에 1을 빼고 대입

후위형 증감 연산자

-> 대입을 먼저 한 후 계산이 일어남 (선 대입, 후 계산)

x++ : x값에 값을 대입하고 1을 더함
x-- : x값에 값을 대입하고 1을 뺌

package ch03.sec01;

public class IncDec {
	public static void main(String[] args) {
		int x = 20;
		int y = 10;
		int z;
		
		x++; // x에 1더함 21
		++x; // x에 1더함 22
		System.out.println("x=" + x);
		
		y--; // 9
		--y; // 8
		System.out.println("y=" + y);
		
		z = x++; // x가 z에 먼저 대입이 되므로 z = 22, x = 23
		System.out.println("z=" + z);
		System.out.println("x=" + x);
		
		z = ++x; // x에 1을 먼저 더하고 z에 대입 z = 24, x=24
		System.out.println("z=" + z);
		System.out.println("x=" + x);
		
		z = ++x + y++; 
       //x는 먼저 1을 더하고 대입, y는 z를 위한 연산 먼저 처리 후 1을 더함 x=25, y=9, z=33
		System.out.println("z=" + z);
		System.out.println("x=" + x);
		System.out.println("y=" + y);
	}

}

산술 연산자

-> +, -, *, /, % : 더하기, 빼기, 곱하기, 나누기, 나머지 구하기
-> %는 나머지 구하는 공식
ex)
6 / 4 = 1 ... 2 일때
6 % 4 = 나머지 값인 2

package ch03.sec02;

public class ArithmeticExam {
	public static void main(String[] args) {
		byte v1 = 15;
		byte v2 = 6;
		int v3 = 5;
		long v4 = 50l;
		
		int result1 = v1 + v2; 
        //피연산자는 모두 int 형태로 변환됨
        
		System.out.println(result1);
		long result2 = v1 + v2 - v4; 
        //long 연산자가 포함된 경우 long 타입의 형태로 변환됨
		System.out.println(result2);
		double result3 = (double) v1/v2; 
        // 실수의 형태로 값을 내기 위해서는 double로 강제 형변환이 필요
		System.out.println(result3);
		int result4 = v1 % v2; 
        // 나머지 연산 구하는 식, 나머지는 정수 형태이기 때문에 int 타입의 형태
		System.out.println(result4);
	}

}

오버플로우와 언더플로우

오버플로우

-> 타입의 허용되는 최대값을 벗어나 타입의 최소값으로 돌아오는 것
ex)
byte의 허용 범위는 -128~127 까지인데
127에서 1을 더하면 128이 나와야 하지만 byte의 허용 범위를 벗어남
그래서 128이 아닌 최소값인 -128로 값이 되돌아와서 출력됨

언더플로우

-> 타입의 허용되는 최소값을 벗어나 타입의 최대값으로 되돌아오는 것
ex)
byte의 허용 범위는 -128~127 까지인데
-128에서 1을 빼면 -129가 나와야 하지만 byte의 허용 범위를 벗어남
그래서 -129가 아닌 최대값 127이 출력됨

package ch03.sec03;

public class OverUnderFlow {
	public static void main(String[] args) {
		byte var1 = 125;
		for(int i=0;i<5;i++) { // 5번 실행
			var1++; 
            //byte 타입의 최대값이 127이기 때문에 값이 넘어가면 최소값인 -128로 되돌아오고 거기서 더해짐
			System.out.println(var1);
		}
		
		byte var2 = -125;
		for(int i=0;i<5;i++) { //5번 실행
			var2--; 
            // byte 타입의 최소값이 -128이기 때문에 값이 넘어가면 최대값인 127로 되돌아오고 1씩 줄어듦
			System.out.println(var2);
		}
	}
}

연산은 정수로 하는 것이 좋은 이유!

-> 정수가 연산 속도나 정밀도가 실수에 비해 훨씬 높음!
-> 실수의 경우 정밀도가 떨어지기 때문에 오차가 발생하여 값이 정확하게 떨어져서 나오지 않을 가능성이 있음

package ch03.sec04;

public class Accuracy1 {
	public static void main(String[] args) {
		int apple = 1; // 사과 1개
		double pieceUnit = 0.1; // 사과 한개를 10조각으로 나눔
		int number = 7; // 7조각
		
		double result = apple - pieceUnit*number; // 남은 사과 조각 계산
		System.out.println(result); 
        // 결과 값 = 0.29999999993
        // 실수의 특성상 오차범위가 있기 때문에 실수간의 계산은 값이 정확하게 떨어지지 않을 수 있음
	}

}

-> 위 코드는 원래대로라면 결과값이 0.3이 나와야 하지만 실수 특성상 오차가 발생하기 때문에 값이 정상적으로 나오지 않음

package ch03.sec04;

public class Accuary2{

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int apple = 1;
		int totalpieces = 10; // 사과 조각의 총 개수를 줌
		int number = 7;
		
		int result = totalpieces - number; 
        // 총 사과 조각 - 먹은 조각 = 남은 조각 -> 정수연산으로 계산
		System.out.println(result);
		System.out.println(result/10.0); 
        // 결과값 = 0.3
        // 정수연산으로 계산했기 때문에 값이 맞아 떨어짐
	}
}

-> 결과 값을 확실하게 도출하기 위해서는 위의 코드처럼 정수 끼리 계산 후에 정수와 실수의 연산으로 값을 도출하면 값이 정확하게 나옴

나눗셈 연산의 예외 사항들

  1. ArithmeticException
    -> 계산 오류
    -> 나눗셈, 나머지 연산에서 좌측 피연산자가 정수, 우측 피연산자가 0일 경우 (0으로 나누거나 나머지를 구할 경우)
  2. Infinity / NaN
    -> 무한대 (Infinity), 숫자가 아님(NaN_
    -> 나눗셈, 나머지 연산에서 좌측 피연사자가 실수, 우측 피연산자가 0.0일 경우

-> Double.isInfinite(x) : x의 값이 무한인지 확인하는 함수
-> Double.isNaN(x) : x의 값이 숫자인지 확인하는 함수

package ch03.sec05;

public class InfinityNaN{

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int x = 6;
		double y = 0.0; // 정수 0으로 나누거나 나머지 값을 구하면 에러가 뜸
		double z = x / y;
		
		if(Double.isInfinite(z) | Double.isNaN(z)) { //Double.isInfinite() : 무한대수인지 확인하는 구문, isNaN() : 숫자가 맞는지 확인하는 구문
			System.out.println("값 산출 불가");
		}
		else {
			System.out.println(z+2);
		}
	}
}

비교 연산자

-> 피연산자를 비교하는 연산자로 주로 조건문(if)이나 반복문 (for, while)의 동작을 제어할 때 사용됨

기본형 타입 비교 연산자

  1. a==b : a와 b의 값이 같은지
  2. a!=b : a와 b의 값이 다른지
  3. a>b / a<b : a가 b보다 크거나 작은지 비교
  4. a>=b / a<=b: a가 b보다 크고 같거나 작거나 같은지 비교

실수의 비교 연산자
-> 실수의 경우 오차 범위가 존재하기 때문에 ==으로 비교하면 안 됨
-> 두 실수간 차를 구하고 그 값에 대한 범위를 구하기
ex) -0.0000000001 < x(두 실수간의 차) && < x < 0.0000000001

-> 더 정확하게 Math.abs()라는 함수를 이용하여 두 실수의 차의 절대값을 구하는 방법도 있음
ex) Math.abs(x(두 실수간의 차)) < 0.000000001

문자열 타입의 비교 연산자

  1. equals() : 문자열이 같은지
  2. !equals() : 문자열이 다른지
    ex) str1.equals(str2) : str1과 str2의 문자열이 같은지
    !str1.equals(str2) : str1과 str2의 문자열이 다른지
package ch03.sec06;

public class CompareExam {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int num1 = 10;
		int num2 = 10;
		boolean result1 = (num1 == num2); 
        // true : num1과 num2가 맞는지
		boolean result2 = (num1 != num2); 
        // false : num1과 num2가 다른지
		boolean result3 = (num1 <= num2); 
        // true : num1보다 num2가 작거나 같은지
		
		System.out.println(result1);
		System.out.println(result2);
		System.out.println(result3);
		
		char char1 = 'A';
		char char2 = 'B';
		boolean result4 = (char1 < char2);
        // true : char1이 char2보다 작은지 (ASCII 코드 값으로 계산됨)
		System.out.println(result4);
		
		int num3 = 1;
		double num4 = 1.0;
		boolean result5 = (num3 == num4); 
        // true : num3과 num4가 같은지
		System.out.println(result5);
		
		float num5 = 0.1f;
		double num6 = 0.1;
		boolean result6 = (num5 == num6); 
        // false : float의 경우 정밀도가 떨어져서 오차범위가 있으므로 정확한 값을 산출하지 못하기에 같지 않음
		boolean result7 = (num5 == (float)num6);
        // true : num6을 float 형태로 바꾸면서 값이 같아짐
		System.out.println(result6);
		System.out.println(result7);
		
		String str1 = "자바";
		String str2 = "Java";
		boolean result8 = (str1.equals(str2)); 
        // str1의 문자열이 str2와 같은지 확인해보는 것 : equlas()는 문자열 비교에 사용됨
		boolean result9 = (!str1.equals(str2)); 
        // str1의 문자열이 str2와 다른지
		System.out.println(result8); // false
		System.out.println(result9); // true
	}

}

논리 연산자

-> 두 개 이상의 연산자의 결과를 확인하기 위해 수행하는 연산자

AND 연산자 (&&, &)

-> 피연산자가 모두 true일 때 결과값이 true

&와 &&의 차이점

&

-> 비교와 연산 작업을 모두 수행
-> 피연산자 a와 b가 있을 때 a의 결과 값이 false여도 연산을 계속 진행함
-> 결과값을 직접 받아서 비교 연산을 수행할 때 사용하는 것이 좋음

&&

-> 비교 작업만 수행
-> 피연산자 a와 b가 있을 때 a의 결과값이 false이면 그대로 실행 종료
-> 실행 자체에는 &&를 사용하는 것이 유리하나 결과값을 직접 받아서 연산을 수행할 경우 동작이 제대로 되지 않을 수도 있음

OR 연산자 (|, ||)

-> 피연산자중 하나만 true이면 결과값이 true

|와 ||의 차이점

|

-> 비교와 연산 작업을 모두 진행
-> 피연산자 a와 b가 있을 때 a의 결과값이 true여도 연산을 계속 수행
-> 결과값을 받아서 비교할 경우 정확한 결과값 도출이 가능

||

-> 비교만 하는 기능
-> 피연산자 a와 b가 있을 때 a의 결과값이 true이면 실행 종료
-> 실행에는 ||을 사용하는 것이 유리하지만, 결과값을 받아서 비교할 경우 정확한 결과값 도출이 어려울 수 있음

XOR 연산자

-> 피연산자의 결과 값이 서로 다르면 true

NOT 연산자

-> 피연산자의 결과를 반대로 표출함
ex) true > false, false > true

package ch03.sec07;

public class LogicalExam {
	public static void main(String[] args) {
		int charCode = 'A';
		
		if ((charCode >= 'A') & (charCode <= 'Z')) { 
        // & : 두개의 연산자가 모두 true일 경우 true 출력
			System.out.println("대문자");
		}
		
		if ((charCode >= 'a') & (charCode <= 'z')) {  
			System.out.println("소문자");
		}
		
		if ((charCode >= '0') & (charCode <= '9')) {
			System.out.println("숫자");
		}
		
		int value = 7;
		
		if((value%2 == 0) | (value%3 == 0)) { 
        // | :  두개의 연산자 중에 하나만 true일 경우 true 출력
			System.out.println("2 또는 3의 배수이군요");
		}
		
		boolean result = (value%2 == 0) || (value%3 == 0);
		if(!result) { 
        // ! : 결과 값의 반대로 출력
			System.out.println("2 또는 3의 배수가 아님");
		}
	}

}

비트 논리, 이동 연산자

비트 논리 연산자

-> bit 단위로 논리 연산을 수행함 (2진수 연산)
-> 피연산자는 0과 1
-> byte, short, int, long만 사용 가능함
-> 최상위 비트가 0이면 양수, 1이면 음수
ex)
양수 = 0000 0000
음수 = 1000 0000

-> AND(&), OR(|), XOR(^), NOT(~) 연산자가 있음 : 원리는 위에 설명한 것과 동일

  • AND 연산자의 경우 mask라고도 불림
    -> 0 부분은 감추고 1이라는 부분만 보여지기 때문

byte 값을 정수로 변환하고자 할때!

  1. byte값 & 255
    -> byte값에 int 정수 255(1111 1111)을 and 연산자를 통해 연산 수행하면 정수로 변환 가능!
    -> 음수의 byte 값의 경우 양수로 출력이 됨
  2. Byte.toUnsignedInt()
    -> Oracle에서 만든 함수로 byte 값을 int 값으로 변환해줌
    -> 사용법
    Byte.toUnsignedInt(x) : byte 변수 x값을 int 값으로 변환
package ch03.sec08;

public class BitLogic{
	public static void main(String[] args) {
		
		int a = 40;
		int b = 18;
		System.out.println(a&b); 
       // 40&18 = 0010 1000 & 0001 0010 => 0000 0000 : 0 (두 bit의 값이 모두 1일 경우에만 1 출력)
		System.out.println(a|b); 
       // 40|18 = 0010 1000 | 0001 0010 => 0011 1010 : 58 (두 bit의 값 중에 하나라도 1이 있으면 1 출력)
		System.out.println(a^b); 
       // 40^18 = 0010 1000 ^ 0001 0010 => 0011 1010 : 58  (두 bit의 값이 서로 다르면 1출력)
		System.out.println(~a); 
       // ~40 = ~0010 1000 => 1101 0111 : -41 (0과 1의 값이 반대로 됨)
		
		byte receiveData = -98;
		
		int unsignedInt1 = receiveData & 255; 
       // byte 값의 데이터와 int 정수의 값을 and 연산자를 통해 정수값을 받고 int 값으로 변환
		System.out.println(unsignedInt1); 
       // 1001 1110 & 1111 1111 = 1001 1110 = 158
		int unsignedInt2 = Byte.toUnsignedInt(receiveData); 
       // Byte.toUnsingedInt : byte 값을 int 값으로 변환해주는 함수
		System.out.println(unsignedInt2); // 158
		
		int test = 158;
		byte btest = (byte) test; 
       //int 타입의 값을 byte값으로 강제 형변환 하는 것
		System.out.println(btest); // -98
	}

}

비트 이동 연산자

a << b

-> 정수 a의 각 bit를 b만큼 왼쪽으로 이동
-> 오른쪽 빈자리는 0으로 채움
-> a x 2^b와 결과값이 동일
ex)
5 << 3 : 00000101 << 3비트씩 왼쪽으로 이동 = 00101000 : 40

a >> b

-> 정수 a의 각 bit를 b만큼 오른쪽으로 이동
-> 왼쪽 빈자리는 최상위 부호 bit와 같은 값으로 채움 (양수는 0, 음수는 1)
-> a / 2^b와 결과값이 동일
ex)
13 >> 2 : 00001101 >> 2비트씩 오른쪽으로 이동 (빈자리는 0으로 채움)
-13 >> 2 : 11110011 >> 2비트씩 오른쪽으로 이동 (빈자리는 1로 채움)

a >>> b

-> 정수 a의 각 비트를 b만큼 오른쪽으로 이동
-> 왼쪽의 빈자리는 0으로 채움 (a<<b의 반대 개념)
ex)
13 >>> 2 : 00001101 >>> 2비트씩 오른쪽으로 이동 = 00000011 : 3
-13 >>> 2 : 11110011 >>> 2비트씩 오른쪽으로 이동 = 00111100 : 60 (byte 연산자일 때 한정)

package ch03.sec09;

public class BitShift {
	public static void main(String[] args) {
		int num1 = 1;
		int result1 = num1 << 4; // num1의 bit를 왼쪽으로 4칸 이동 후 빈공간을 0으로 채움
		int result2 = num1 * (int)Math.pow(2, 4); // 2의 4승을 계산 후 double값으로 출력하기에 정수로 출력하려면 int 타입의 형태로 변환해야함
		
		System.out.println(result1); // 16
		System.out.println(result2); // 16
		
		int num2 = -16;
		int result3 = num2 >> 3; // num2의 bit를 오른쪽으로 3칸 이동 후 빈공간을 최상위 비트 숫자로 채움 (양수:0, 음수:1)
		int result4 = num2 / (int)Math.pow(2, 3); // num2의 값을 2의 3승으로 나눔
		
		System.out.println(result3); //-2
		System.out.println(result4); //-2
	}
}

대입 연산자

-> 우측 피연산자의 값을 좌측 피연산자에 대입하고 우측 피연산자와의 연산을 수행함
-> 우측 피연산자가 연산식일 경우 우측 피연산자의 연산식을 수행 후 좌측 피연산자에 대입 후 연산 시행!

대입 연산자의 종류

  1. a=b : b의 값을 a에 저장
  2. a+=b : a=a+b
  3. a-=b : a=a-b
  4. a 별표= b : a = a별표b -> 곱셈
  5. a/=b : a=a/b
  6. a%=b : a=a%b
  7. a&=b : a=a&b
  8. a|=b : a=a|b
  9. a^=b : a=a^b
  10. a<<=b : a = a << b
  11. a>>=b : a = a >> b
  12. a>>>=b : a = a >>> b
package ch03.sec10;

public class AssignmentExam {
	public static void main(String[] args) {
		int result = 0; //result라는 초기값을 설정해야함
		result += 10; // result = result + 10
		System.out.println(result); // 10
		result -= 5; // result = result - 5
		System.out.println(result); // 5
		result *= 3; // result = result * 3
		System.out.println(result); // 15
		result /= 3; // result = result / 3
		System.out.println(result); // 5
		result %= 3; // result = result % 3 (3으로 나눴을 때 나머지 구하기)
		System.out.println(result); // 2
	}

}

삼항 연산자

-> 3개의 피연산자를 가짐
-> 구조:
조건식(피연산자1) ? 값/연산식(피연산자2) : 값/연산식(피연산자3)
-> 피연산자1은 조건식이므로 boolean 값을 가지게 됨
-> 피연산자1의 결과값이 true이면 피연산자2가 false이면 피연산자3이 출력

package ch03.sec11;

public class exam01 {
	public static void main(String[] args) {
		int score = 85;
		char grade = (score > 90) ? 'A' : (score>80) ? 'B' : (score>70) ? 'C' : 'D'; // 90점이상:A, 80점이상:B, 70점이상:C, 미만:D
//		 : 3개의 피연산자를 가진다
//		 : 조건식(피연산자1) ? 값 또는 연산식(피연산자2) : 값 또는 연산식(피연산자3)의 구조
//		 : 피연산자1의 경우 boolean 변수를 가짐
//		 : 피연산자1의 결과값이 true이면 피연산자2의 값이, false이면 피연산자3의 값이 출력됨.
		System.out.println(grade);
	}

}
profile
끄작끄작

0개의 댓글