본문 바로가기
자바공부/연산자

JAVA(자바) - 이항 연산자 1. 산술 연산자(+, -, *, /, %)

by You진 2020. 12. 23.

이항 연산자

-피연산자가 2개인 연산자

-종류

  ● 산술 연산자 : +, -, *, /, %

  ● 문자열 연결 연산자: +

  ● 비교 연산자 : <, <=, >, >=, ==, !=

  ● 논리 연산자 : &&, ||, &, |, ^, !

  ● 비트 논리 연산자 : &, |, ^

  ● 비트 이동 연산자 : <<, >>, >>>

  ● 대입 연산자 : =, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>=

 

이항 연산자 종류를 한번 보자.

 

1.산술 연산자( +, -, *, /, % )

연산식 설명
피연산자 + 피연산자 덧셈 연산
피연산자 - 피연산자 뺄셈 연산
피연산자 * 피연산자 곱셈 연산
피연산자 / 피연산자 좌측 피연산자를 우측 피연산자를 나눗셈을 연산
피연산자 % 피연산자 좌측 피연산자를 우측 피연사자를 나눈 나머지를 구하는 연산

- boolean 타입을 제외한 모든 기본 타입에 사용 가능

- 산술 연산에서의 타입 변환

1. 피연산자들이 모두 정수 타입이고, int 타입 보다 크기가 작은 타입일 경우 모두 int 타입으로 변환 후에 연산을 수행한다. 따라서 연산의 산출 타입은 int 이다.
예) byte + byte -> int + int = int

2. 피연산들이 모두 정수 타입이고 long 타입이 있을 경우 모두 long 타입으로 변환 후에 연산을 수행한다. 따라서 연산의 산출 타입은 long이다
예) int + long -> long + long = long

3.피연산자중 실수 타입(float 타입, double 타입)이 있을 경우, 크기가 큰 실수 타입으로 변환후에 연산을 수행한다. 따라서 연산의 산출 타입은 실수 타입이다.
에) int + double -> double + double = double

public class ArithmeticOperatorExample {
	public static void main(String[] args) {
		int v1 =5;
		int v2 = 2;
		
		int result1 = v1+v2;
		System.out.println("result1="+result1);
		
		int result2 = v1 -v2;
		System.out.println("result2="+result2);
		
		int result3 = v1*v2;
		System.out.println("result3="+result3);
		
		int result4 = v1/v2;
		System.out.println("result4="+result4);
		
		int result5 = v1%v2;
		System.out.println("result5="+result5);
		
		double result6 = (double)v1/v2;
		System.out.println("result6="+result6);
	}
}
실행 후 결과 값:
result1=7
result2=3
result3=10
result4=2
result5=1
result6=2.5
public class CharOperationExample {
	public static void main(String[] args) {
		char c1 ='A'+1;
		char c2 ='A';
		//char c3 = c2+1; 에러
		//에러 난 이유 c1은 상관없는데 c3는 c2에 가지고 있는 A에다가 1을 더한다
		//그러면 c3는 int 형식으로 들어가기 때문에 오류가난다
		//에러가 안나려면 강제 char 변환
		System.out.println("c1: "+c1);
		System.out.println("c2: "+c2);
		//System.out.println("c3: "+c3);
	}
}
실행 후 결과 값:
c1: B
c2: A

 

- 오버플로우로 인해 잘못된 값이 산출되는 것을 방지

public class OverflowExample {
	public static void main(String[] args) {
		//오버플로우 경우
        /* 
		int x = 1000000;
		int y = 1000000;
		
		int z = x*y;
		System.out.println(z);
		//값 -727379968 <-- 쓰레기 값이라고 한다 (int 타입 범위를 초과하여서 오버플로우)
        
        //오버플로우 해결
		*/
		long x = 1000000;
		long y = 1000000;
		
		long z = x*y;
		System.out.println(z);
		//long 타입이 도면 정상적인 연산
		//값 1000000000000
	}
}

 

-산술 연산 전에 오버플로우를 탐지

public class CheckOverflowExample {
	public static void main(String[] args) {
		try {
			int result = safeAdd(2000000000,2000000000);
			System.out.println(result);
		} catch (ArithmeticException e) {
			System.out.println("오버플로우가 발생하여 정확하게 계산할수 없음");
		}
	}
	public static int safeAdd(int left, int right) {
		if (right>0) {
			if (left>(Integer.MAX_VALUE - right)) {
				throw new ArithmeticException("오버플로우 발생");
			}
		}else {
			if (left<(Integer.MIN_VALUE - right)) {
				throw new ArithmeticException("오버플로우 발생");
			}
		}
		return left+right;
	}
}
실행 후 결과 값:
오버플로우가 발생하여 정확하게 계산할수 없음

 

-정확한 계산은 정수를 사용

 ● 정확하게 계산해야할 떄는 부동소수점(실수)타입을 사용하지 않는 것이 좋다.

public class AccuracyExample1 {
	public static void main(String[] args) {
		int apple = 1;
		double pieceUnit = 0.1;
		int number = 7;
		double result = apple - number * pieceUnit;
		System.out.println("사과 한개에서");
		System.out.println("0.7조각을 빼면,");
		System.out.println(result + "조각이 남는다");
	}
}
실행 후 결과 값:
사과 한개에서
0.7조각을 빼면,
0.29999999999999993조각이 남는다

결과값이 애매하게 나온다.
그 이유는 부동소수점 타입(flaot,double)은 0.1을 정확히 표현할 수 없어 근사치로 처리하기 때문이다.

위에 결과값을 보고 정확한 결과값을 산출하려면...

public class AccuracyExample2 {
	public static void main(String[] args) {
		int apple = 1;

		int totalPieces = apple * 10;
		int number = 7;
		int temp = totalPieces - number;
		double result = temp / 10.0;

		System.out.println("사과 한개에서");
		System.out.println("0.7조각을 빼면,");
		System.out.println(result + "조각이 남는다");
	}
}
실행 후 결과 값:
사과 한개에서
0.7조각을 빼면,
0.3조각이 남는다

 

-NaN과 Infinity 연산을 조심하자

NaN : 연산 과정에서 잘못된 입력을 받았음을 나타내는 기호

Infinity : 무한대

 

 

public class InfinityAndNaNCheckExample {

	public static void main(String[] args) {
		
		int x = 5;
		double y = 0.0;
        
		double z = x / y; 
		//double z = x%y;
		
        	System.out.println(Double.isInfinite(z));
		System.out.println(Double.isNaN(z));
		
        	System.out.println(z + 2);// 문제가 되는 코드
		
        	여기까지만 했을때 실행 값은 :
		false
		true
		NaN
        
        //----------------------------
        
		if (Double.isInfinite(z) || Double.isNaN(z)) {
			System.out.println("값 산출불가");
		} else {
			System.out.println(z);
		}
        요거 값은 :
        값 산출불가
	}
}

-입력된 문자열을 숫자로 변환할 때 NaN인지 검사

부동소수점(실수)을 입력받을 때는 NaN 검사를 해야 한다.

public class InputDataCheckNaNExample2 {
	public static void main(String[] args) {
		String userInput = "NaN";		//사용자로부터 입력받은 값
		double val = Double.valueOf(userInput); //입력값을 double타입으로변환
		
		double currentBalance = 10000.0;
		
		currentBalance = currentBalance +val;	//currentBalance에 NaN이 저장됨
		//currentBalance += val;
		System.out.println(currentBalance);
	}
}
		실행 결과 값:
        	NaN
		연산이 됬다. 연산이 되면 안되는데 됬다 해답은 아래

Double.valueOf() 메소드가 double 타입으로 변환 그럼 NaN이 저장이 된다.

그리고 산술 연산을 수행하면 안되는데 산술연산이 가능하다

NaN이랑 아무 수랑 연산을 하면 NaN이 산출되어서 엉망이 된다.

 

그래서 NaN을 체크를 하고 연산 수행을 해줘야된다.

public class InputDataCheckNaNExample {
	public static void main(String[] args) {
		String userInput = "NaN";
		double val = Double.valueOf(userInput);
		double currentBalance = 10000.0;
		if (Double.isNaN(val)) {
			System.out.println("NaN이 입력되어 처리할 수 없음");
			val = 0.0;
		}
		currentBalance += val;
		System.out.println(currentBalance);
	}
}
		실행 후 결과 값:
		NaN이 입력되어 처리할 수 없음
		10000.0