Java/이것이자바다_개념정리

Java 기초 정리 2차_3)연산자_이것이 자바다

김쟈워니 2024. 5. 27. 12:16
부호/증감 연산자
  •  부호 연산자는 변수의 부호를 유지하거나 변경한다.
연산식 설명
+ 피연산자 피연산자의 부호 유지
- 피연산자 피연산자의 부호 변경
  • + 연산자는 잘 사용되지 않고, - 연산자는 변수값의 부호를 변경할 때 사용된다.
    • 부호를 변경하는 것도 연산이므로 byte, short, int 의 연산 결과를 int에 대입해야 함
package ch03.sec01;

public class SingOperatorExample {

	public static void main(String[] args) {
		int x = -100;
		x=-x;
		System.out.println("x: " + x);
		
		byte b = 100;
		int y =-b;
		;System.out.println("y: "+ y);
	}

}
==============================================
콘솔 출력문
x: 100
y: -100
==============================================
연산식 설명
++ 피연산자 피연산자의 값을 1 증가 시킴
-- 피연산자 피연산자의 값을 1 감소 시킴
피연산자 ++ 다른 연산을 수행한 후에 피연산자의 값을 1 증가시킴
피연산자 -- 다른 연산을 수행한 후에 피연산자의 값을 1 감소시킴
  • 변수 단독으로 증감 연산자가 사용될 경우 변수 앞 뒤 어디에 붙어도 결과 동일
    • ++i; i++; 모두 i=i+1; 로 동일
    • --i;i--; 모두 i=i-1l로 동일
  • 여러 개의 연산자가 포함되어 있는 연산식에서는 증감 연산자의 위치에 따라 결과가 달라짐
    • 증감 연산자가 변수 앞에 있으면 우선 변수를 1증가 또는 1 감소시킨 후에 다른 연산을 수행
    • 증감 연산자가 변수 뒤에 있으면 모든 연산을 끝낸 후에 변수를 1증가 또는 1 감소
package ch03.sec01;

public class IncreaseDecreaseOperatorExample {

	public static void main(String[] args) {
		int x = 10;
		int y = 10;
		int z;

		x++;
		++x;
		System.out.println("x= " + x);

		System.out.println("-----------------");
		y--;
		--y;
		System.out.println("y= " + y);

		System.out.println("-----------------");
		z = x++;
		System.out.println("z= " + z);
		System.out.println("x= " + x);

		System.out.println("-----------------");
		z = ++x;
		System.out.println("z= " + z);
		System.out.println("x= " + x);

		System.out.println("-----------------");
		z = ++x + y++;
		System.out.println("z= " + z);
		System.out.println("x= " + x);
		System.out.println("y= " + y);
	}

}
===========================================================
콘솔 출력문
===========================================================
x= 12
-----------------
y= 8
-----------------
z= 12
x= 13
-----------------
z= 14
x= 14
-----------------
z= 23
x= 15
y= 9
  • 변수 단독으로 사용될때 x++;와 x++; 모두 +1로 결과는 동일
    • y--;와 --y; 역시 모두 -1 하는 결과
  • 연산식에서는 증감위치에 따라 결과 달라졌음
    • z=x++; 에서 z에는  x값이 들어가고, 그 이후에 x 값이 +1 됨
    • z=++x; 에서는 z에 x값이 +1 된후 z에 그 값이 대입됨
    • z= ++x + y++; 에서는 x 값이 +1 이 됨, y++에서는 이 모든 연산이 끝난 후 y값 +1 이므로 
      • z= +1이 된 x값과 현재 y값을 더하여 15+8의 값이 되어야 함. 


산술연산자
  • 산술 연산자는 더하기(+),빼기(-),곱하기(*),나누기(/),나머지(%)로 총 5개
연산식 설명
피연산자 + 피연산자 덧셈연산
피연산자 - 피연산자 뺄셈 연산
피연산자 * 피연산자 곱셈 연산
피연산자 / 피연산자 나눗셈 연산
피연산자 % 피연산자 나눗셈의 나머지를 산출하는 연산
  • 곱셈의 경우 *를 사용하고 나눗셈의 경우/를 사용한 다는 것이 일반 수학과 다름
  • 산술 연산의 특징
    • 피연산자가 정수 타입(byte,short,char,int) 이면 연산의 결과는 int
    • 피연산자가 정수 타입이고, 그 중 하나가 long 타입이면 연산의 결과는 long 타입
    • 피연산자 중 하나가 실수 타입이면 연산의 결과는 실수 타입
package ch03.sec01;

public class ArithmeticOperatorExample {

	public static void main(String[] args) {
		byte v1 = 10;
		byte v2 = 4;
		int v3 = 5;
		long v4 = 10L;

		int result1 = v1+ v2;
		System.out.println("result1: " +result1);
		
		long result2 = v1+ v2 -v4;
		System.out.println("result2: " +result2);
		
		double result3=(double)v1/v2;
		System.out.println("result3: " +result3);
		
		int result4 = v1%v2;
		System.out.println("result4: " +result4);
	}

}

오버플로우와 언더플로우
  • 오버플로우(overflow)
    • 타입이 허용하는 최대값을 벗어나는 것
  • 언더플로우(underflow)
    • 타입이 허용하는 최소값을 벗어나는 것
  • 정수 타입연산에서 오버플로우 또는 언더플로우가 발생되면 해당 정수타입의 최소값 또는 최대값으로 되 돌아감.
package ch03.sec01;

public class OverflowUnderflowExample {

	public static void main(String[] args) {
		byte var1 = 125;
		for(int i=0; i<5; i++) {
			var1++;
			System.out.println("var1: "+ var1);
		}
		
		System.out.println("=======================");
		
		byte var2 = -125;
		for(int i=0;i<5;i++) {
			var2--;
			System.out.println("var2: "+ var2);
		}

	}

}
===========================================================
콘솔출력문
===========================================================
var1: 126
var1: 127
var1: -128
var1: -127
var1: -126
=======================
var2: -126
var2: -127
var2: -128
var2: 127
var2: 126
  • short,int,long 타입 역시 값의 범위만 다를 뿐 오버플로우 와 언더플로우 가 발생하며 최소값과 최대값으로 되돌아감

정확한 계산은 정수 연산으로 
  •  산술 연산을 정확하게 계산하고 싶다면 실수 타입을 사용하지 않는 것이 좋음
package ch03.sec04;

public class AccuracyExample {

	public static void main(String[] args) {
		int apple =1;
		double pieceUnit =0.1;
		int number =7;
		
		double result = apple - number*pieceUnit;
		System.out.println("사과 1개에서 남은 양: " + result);
	}

}
===============================================================
콘솔 출력문
===============================================================
사과 1개에서 남은 양: 0.29999999999999993
  • 부동 소수점 방식을 사용하는 실수 타입에서 흔히 일어나는 문제 그래서 아래와 같이 계산하는 것이 좋음
package ch03.sec04;

public class AccuracyExample2 {

	public static void main(String[] args) {
		int apple = 1;
		int totalPieces = apple * 10;
		int number = 7;
		
		int result = totalPieces - number;
		System.out.println("10조각에서 남은 조각: "+ result);
		System.out.println("사과 1개에서 남은 양: " + result/10.0);
	}

}
=====================================================================
콘솔 출력문
=====================================================================
10조각에서 남은 조각: 3
사과 1개에서 남은 양: 0.3

나눗셈 연산 후 NaN과 Infinity 처리
  • 나눗셈(/) 또는 나머지(%) 연산 에서 좌측 피연산자가 정수이고 우측 피연산자가 0일 경우 예외(AritmeticException)이 발생 
    • 무한대의 값을 정수로 표현할 수 없기 때문
  • 좌측 피연산자가 실수이거나 우측 피연산자가 0.0 또는 0.0F이면 예외가 발생하지 않고 연산의 결과는 Infinity(무한대)또는 NaN(Not a Number) 가 된다.
    • Infinity 또는 NaN 상태일 때는 연산을 계속 수행하면 안됨. 어떤 연산을 하더라도 계속해서 Infinity와 NaN이 됨
      • 실수의 /와 % 연산의 결과가 Infinity 또는 NaN인지 확인하고 연산 수행, 그 확인 방법
        • Double.isInfinite() 와 Double.isNaN() 메서드 사용
          • Infinity 또는 Nan 일 경우 true, 아닐 경우 false 
package ch03.sec05;

public class InfinityAndNaNCheckExample {

	public static void main(String[] args) {
		int x =5 ;
		double y =0.0;
		double z = x/y;
		
		System.out.println(z+2);
		
		if(Double.isInfinite(z)||Double.isNaN(z)) {
			System.out.println("값 산출 불가");
		}else {
			System.out.println(z+2);
		}
	}

}
======================================================
콘솔 출력문
======================================================
Infinity
값 산출 불가

비교 연산자
  • 비교 연산자는 동등/ 또는 크기 비교를 평가하여 boolean 타입인 true/false 를 산출한다
    • 비교연산자는 주로 흐름제어문인 조건문(if),반복문(for,while)에서 실행 흐름을 제어할 때 주로 사용됨
구분 연산식 설명
동등 비교 피연산자 1 == 피연산자 2 두 피연산자의 값이 같은지 검사
피연산자 1 != 피연산자 2 두 피연산자의 값이 다른지 검사
크기 비교 피연산자 1 > 피연산자 2 피연산자 1이 큰지 검사
피연산자 1 >= 피연산자 2 피연산자 1이 크거나 같은지 검사
피연산자 1 < 피연산자 2 피연산자 1이 작은지 검사
피연산자 1 <= 피연산자 2 피연산자 1이 작거나 같은지 검사
  • 피연산자의 타입이 다를 경우 비교 연산을 수행하기 전 타입을 일치시킴
    • 'A' == 65 는 char 가 int 로 변환되어 65 == 65 로 비교됨
    • 3==3.0은 int 가 double 로 변환되어 3.0 == 3.0 으로 비교됨
    • 예외
      • 0.1F== 0.1 은 float가 double 로 변환되어 0.1 == 0.1 로 true 산출 되어야하지만 false 산출 됨
        • 부동 소수점 방식을 사용하는 실수 타입은 0.1 을 정확히 표현할 수 없음
        • float타입과 double 타입의 정밀도 차이
        • 피연산자를 float타입으로 강제 타입 변환후 비교연산
    • 문자열을 비교할 때는 동등(==,!=) 연산자 대신 equals()와 !eqauls()를 사용
package ch03.sec06;

public class CompareOperatorExampler {

	public static void main(String[] args) {
		int num1 = 10;
		int num2 = 10;
		boolean result1 = (num1 == num2);
		boolean result2 = (num1 != num2);
		boolean result3 = (num1 <= num2);

		System.out.println("result1: " + result1);
		System.out.println("result2: " + result2);
		System.out.println("result3: " + result3);

		char char1 = 'A';
		char char2 = 'B';
		boolean result4 = (char1 < char2);
		System.out.println("result4: " + result4);

		int num3 = 1;
		double num4 = 1.0;
		boolean result5 = (num3 == num4);
		System.out.println("result5: " + result5);

		float num5 = 0.1f;
		double num6 = 0.1;
		boolean result6 = (num5 == num6);
		boolean result7 = (num5 == (float) num6);
		System.out.println("result6: "+ result6);
		System.out.println("result7: "+ result7);
		
		String str1="자바";
		String str2="Java";
		boolean result8 =(str1.equals(str2));
		boolean result9 =(!str1.equals(str2));
		System.out.println("result8: "+ result8);
		System.out.println("result9: "+ result9);
	}

}
=====================================================
콘솔출력문
=====================================================
result1: true
result2: false
result3: true
result4: true
result5: true
result6: false
result7: true
result8: false
result9: true

논리 연산자
  • 논리 연산자는 논리곱(&&), 논리합(||), 배타적 논리합(^), 그리고 논리 부정(!) 연산을 수행
  • 흐름 제어문인 조건문(if),반복문(for,while) 등에서 주로 이용됨
구분 연산식 결과 설명
AND
(논리곱)
true &&
또는
&
true true 피연산자 모두가 true일 경우에만 연산결과가 true
true false false
false true false
false false false
OR
(논리합)
true ||
또는
|
true true 피연산자 중 하나만 true 이면 연산 결과는 true
true false true
false true true
false false false
XOR
(배타적 논리합)
true ^ true false 피연산자가 하나는 true이고 다른 하나가 false 일 경우에만 연산결과가 true
true false true
false true true
false false false
NOT
(논리 부정)
  ! true false 피연산자의 논리값을 바꿈
false true
  • && 와 &의 연산과정에서 차이
    • &&는 앞의 피연산자가 false라면 뒤의 피연산자를 평가하지 않고 바로 false 를 산출
    • &는 두 피연산자 모두 평가해서 산출의 결과를 냄
    • & 보다는 &&가 효율적으로 동작
  • ||와|의 연산과정에서의 차이 
    • ||는 앞의 피연산자가 true라면 뒤의 피연산자를 평가하지 않고 바로 true 산출
    • |는 두 피연산자 모두를 평가해서 산출의 결과를 냄
    • |보다는 ||가 효율적으로 동작
package ch03.sec07;

public class LogicalOperatorExample {

	public static void main(String[] args) {
		int charCode='A';
		//int charCode='a';
		//int charCode='5';
		
		if((65<=charCode)&(charCode<=90)){
			System.out.println("대문자");
		}
		
		if((97<=charCode)&&(charCode<=122)) {
			System.out.println("소문자");
		}
		
		if((48<=charCode)&&(charCode<=57)) {
			System.out.println("0~9사이의 숫자");
		}
		
		
//==================================================
		
		int value =6;
		//int value =7;
		
		if((value%2==0)|(value%3==0)){
			System.out.println("2의 배수 또는 3의 배수");
		}
		
		boolean result = (value%2==0)||(value%3==0);
		if(!result) {
			System.out.println("2또는 3의 배수가 아니군요");
		}
	}

}
==============================================================
콘솔 출력문
==============================================================
대문자
2의 배수 또는 3의 배수
  • 해당 코드의 주석이 되어있는 변수 선언 및 초기화문들을 사용해가며 다른 값을 볼 수 있음

비트 논리 연산자
  • 비트 논리 연산자는 bit 단위로 논리 연산을 수행.
    • 0과 1이 피연산자가 되무르 2진수 0과 1로 저장되는 정수타입(byte,short,int,long)만 피연산자가 될 수 있음
      • 부동 소수정 방식으로 저장되는 실수 타입(float,double)은 피연산자가 될 수 없음
구분 연산식 결과 설명
AND
(논리곱)
1 & 1 1 두 비트 모두 1일 경우에만 연산 결과가 1
1 0 0
0 1 0
0 0 0
OR
(논리합)
1 | 1 1 두 비트 중 하나만 1이면 연산 결과는 1
1 0 1
0 1 1
0 0 0
XOR
(배타적 논리합)
1   1 0 두 비트 중 하나는 1이고 다른 하나는 0이면 연산 결과는 1
1 0 1
0 1 1
0 0 0
NOT
논리부정
  ~ 1 0 비트값이 0 일경우 1로, 1일 값일 경우 0으로 변경함
  0 1
package ch03.sec08;

public class BitLogicExample {

	public static void main(String[] args) {
		System.out.println("45 & 25 = " + (45&25));
		System.out.println("45 | 25 = " + (45|25));
		System.out.println("45 ^ 25 = " + (45^25));
		System.out.println("~45 = " + (~45));
		System.out.println("===========================");
		
		
		byte receiveData=-120;
		//비트 논리곱 연산으로 Unsigned 정수 얻기
		int unsignedInt1 = receiveData&255;
		System.out.println(unsignedInt1);
		//자바 API를 이용해서 Unsigned 정수 얻기
		int unsignedInt2 = Byte.toUnsignedInt(receiveData);
		System.out.println(unsignedInt2);
		
		int test=136;
		byte btest=(byte)test;
		System.out.println(btest);
	}

}
===============================================================
콘솔출력문
===============================================================
45 & 25 = 9
45 | 25 = 61
45 ^ 25 = 52
~45 = -46
===========================
136
136
-120

비트 이동 연산자
  • 비트 이동 연산자는 비트를 좌측 또는 우측으로 밀어서 이동시키는 연산을 수행
구분 연산식 설명
이동
(shift)
a << b 정수 a의 각 비트를 b만큼 왼쪽으로 이동
오른쪽 빈자리는 0 으로 채움
2ᵇ 과 동일한 결과
a >> b 정수 a 의 각 비트를 b 만큰 오른쪽으로 이동
왼쪽 빈자리는 최상위 부호 비트와 같은 값으로 채움
a/ 2ᵇ과 동일한 결과가 됨
a >>> b 정수 a의 각 비트를 b 만큼 오른쪽으로 이동
왼쪽 빈자리는 0으로 채움
  • 비트연산자 << , >> 활용하기 예시
package ch03;

public class BitShiftExample1 {

	public static void main(String[] args) {
		int num1=1;
		int result1 =num1<<3;
		int result2 = num1 *(int)Math.pow(2, 3);//Math.pow(2,3)은 2^3을 연산하고, double 값을 산출. 
		//int 값을 얻고 싶다면 (int)로 캐스팅 해야함
		
		System.out.println("result1: "+ result1);
		System.out.println("result2: "+ result2);
		
		int num2=-8;
		int result3= num2>>3;
		int result4=num2/(int)Math.pow(2, 3);
		
		System.out.println("result3: "+ result3);
		System.out.println("result4: "+ result4);
	}

}
  • 좌측 이동 연산자(<<)를 사용하여 정수 1을 3비트만큼 왼쪽으로 이동
    • 4byte 전체를 왼쪽으로 3비트 이동하면 맨 왼쪽 3비트는 밀려서 버려지고, 오른쪽 새로 생기는 3비트는 0으로 채워짐
    • 이 값음 1에 2^3을 곱 한 것과 값이 같음
  • 우측이동연산자(<<)를 사용하여 정수 -8을 3비트만큼 오른쪽으로 이동
    • 4byte 전체를 오른쪽으로 3비트 이동할 때 맨 오른쪽 3비트는 밀려서 버려지고, 맨 왼쪽 새로 생기는 3비트는 최상위 부호 비트와 동일한 값으로 채워짐
      • 즉, 음수이면 1이 양수이면 0이 채워짐
    • 이 값은 -8을 2^3을 나눈 것과 값이 같음
  • int 타입 값 772를 구성하는 4개의 byte를 각각 별도로 읽고, 부호 없는 정수(0~255)로 출력하는 예제
package ch03.sec09;

public class BitShiftExample2 {

	public static void main(String[] args) {
		int value = 772; // [00000000] [00000000] [00000011] [00000100]

		// 우측으로 3byte(24bit) 이동하고 끝 1바이트만 읽음 : [00000000]
		byte byte1 = (byte) (value >>> 24);
		int int1 = byte1 & 255;
		System.out.println("첫 번째 바이트 부호 없는값: " + int1);

		// 우측으로 2byte(16bit) 이동하고 끝 1바이트만 읽음: [00000000]
		byte byte2 = (byte)(value>>>16);
		int int2=Byte.toUnsignedInt(byte2);
		System.out.println("두 번째 바이트 부ㅗ 없는 값: " + int2);
		
		// 우측으로 1byte(8bit) 이동하고 끝 1바이트만 읽음: [00000011]
		byte byte3 = (byte)(value>>>8);
		int int3 = byte3&255;
		System.out.println("세 번째 바이느 부호 없는 값: " + int3);
		
		//끝 1바이트만 읽음:[00000100]
		byte byte4=(byte)value;
		int int4 = Byte.toUnsignedInt(byte4);
		System.out.println("네 번째 바이트 부호 없는 값: " + int4);
	}

}
  • 솔직히 이해못함 ㅠ

대입 연산자
  • 대입 연산자
    • 우측 피연산자의 값을 좌측 피연산자인 변수에 대입한다
    • 우측 피연산자에는 리터럴 및 변수, 그리고 다른 연산식이 올 수 있다.
    • 대입연산자의 종류
      • 단순 대입 연산자
        • 단순히 값을 대입
      • 복합 대입 연산자
        • 정해진 연산을 수행 후 결과를 대입
구분 연산식 실행
단순 대입 연산 변수 = 피연산자 우측의 피연산자의 값을 변수에 저장
복합 대입 연산 변수 += 피연산자 우측의 피연산자의 값을 변수의 값과 더한 후에 다시 변수에 저장
(변수= 변수 + 피연산자)
변수 -= 피연산자 우측의 피연산자의 값을 변수의 값과 뺀 에 다시 변수에 저장
(변수= 변수 - 피연산자)
변수 *= 피연산자 우측의 피연산자의 값을 변수의 값과 곱한 후에 다시 변수에 저장
(변수= 변수 * 피연산자)
변수 /= 피연산자 우측의 피연산자의 값을 변수의 값과 나눈 후에 다시 변수에 저장
(변수= 변수 / 피연산자)
변수 %= 피연산자 우측의 피연산자의 값을 변수의 값과 나눈 후에 나머지를 변수에 저장
(변수= 변수 % 피연산자)
변수 &= 피연산자 우측의 피연산자의 값을 변수의 값과 &연산 후에 다시 변수에 저장
(변수= 변수 & 피연산자)
변수 |= 피연산자 우측의 피연산자의 값을 변수의 값과 |연산 후에 다시 변수에 저장
(변수= 변수 | 피연산자)
변수 ^= 피연산자 우측의 피연산자의 값을 변수의 값과 ^연산 후에 다시 변수에 저장
(변수= 변수 ^ 피연산자)
변수 <<= 피연산자 우측의 피연산자의 값을 변수의 값과 <<연산 후에 다시 변수에 저장
(변수= 변수 << 피연산자)
변수 >>= 피연산자 우측의 피연산자의 값을 변수의 값과 >>연산 후에 다시 변수에 저장
(변수= 변수 >> 피연산자)
변수 >>>= 피연산자 우측의 피연산자의 값을 변수의 값과 >>>연산 후에 다시 변수에 저장
(변수= 변수 >>> 피연산자)
package ch03.sec10;

public class AssignmentOperatorExample {

	public static void main(String[] args) {
		int result = 0;
		result +=10;
		System.out.println("result= "+ result);
		result-=5;
		System.out.println("result= "+ result);
		result *=3;
		System.out.println("result= "+ result);
		result /=5;
		System.out.println("result= "+ result);
		result %=3;
		System.out.println("result= "+ result);
	}

}
===============================================
콘솔출력문
===============================================
result= 10
result= 5
result= 15
result= 3
result= 0

삼항(조건) 연산자
  • 삼항연산자는 피연산자는 총 3개
    • 피연산자1?피연산자2:피연산자3
      • ?앞의 피연산자는 boolean 변수 또는 조건식
      • ? 앞의 피연산자 값이 true이면 콜론(:) 앞의 피연산자(피연산자 2)가 선택
      • ? 앞의 피연산자 값이 false 이면 콜론 뒤의 피연산자(피연산자 3)가 선택
    • 피연산자 2와 3에는 주로 값이 오지만, 경우에 따라서 연산식도 가능
package ch03.sec11;

public class ConditionOperationExample {

	public static void main(String[] args) {
		int score=85;
		char grade=(score>90)?'A':((score>80)?'B':'C');
		System.out.println(score + "점은"+ grade + "등급입니다." );
	}

}
===================================================================
콘솔출력문
===================================================================
85점은B등급입니다.

연산의 방향과 우선순위
연산자 연산 방향 우선 순위
증감(++,--),부호(+,-),비트(~),논리(!) 오른쪽에서 왼쪽으로
높음






































낮음
산술(*,/,%) 왼쪽에서 오른쪽으로
산술(+,-) 왼쪽에서 오른쪽으로
쉬프트(<<,>>,>>>) 왼쪽에서 오른쪽으로
비교(<,>,<=,>=,instanceof) 왼쪽에서 오른쪽으로
비교(==,!=) 왼쪽에서 오른쪽으로
논리(&) 왼쪽에서 오른쪽으로
논리(^) 왼쪽에서 오른쪽으로
논리(|) 왼쪽에서 오른쪽으로
논리(&&) 왼쪽에서 오른쪽으로
논리(||) 왼쪽에서 오른쪽으로
조건(?:) 왼쪽에서 오른쪽으로
대입(=,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>=,>>>=) 오른쪽에서 왼쪽으로
  • 가장 먼저 처리해야할 연산은 괄호() 로 묶음 , 괄호 는 최 우선 순위를 가짐