프로그래밍 언어/JAVA

[JAVA] 이항 연산자(1) -산술 연산자, 문자열 연결 연산자

김곰댕 2021. 6. 8. 17:19
728x90

이항 연산자

피연산자가 2개인 연산자

종류 : 산술연산자(+, -, *. /, %), 문자열 연결 연산자(+), 대입연산자(=, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>=), 비교연산자(<, <=, >, >=, ==, !=), 논리연산자(&&, ||, &, |, ^, !), 비트 논리 연산자(&, |, ^), 비트 이동 연산자(<<, >>, >>>)


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

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

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

산술 연산에서의 타입변환

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

예) byte + byte -> int + int = int

char c1 = 'A' + 1; //c1 에 65+1 =66 값인 'B'가 저장되게됨

char c2 = 'A'

//char c3 = c2 + 1;  //컴파일 에러 - 위의 c1과는 달리 연산자로 인해 c2가 int타입으로 변화되었음, 따라서 int값인 66은 c3에 저장할 수가 없음. 이 경우 char c3 = (char)(c2+1); 과 같이 char 타입으로 강제 타입변환을 해주어야함 

예제)

package sec04.exam01_arithmetic;

public class CharOperationExample 
{
	public static void main(String[] args) 
	{
		char c1 = 'A' + 1; //char타입
		char c2 = 'A';
		
		int result = c2 + 1; //연산자를 사용하면서 c2가 int 타입으로 바뀜
		char c3 = (char)(c2 + 1); //char타입으로 강제 타입변환
		
		System.out.println("c1의 값 : "+c1);
		System.out.println("result의 값 : "+result);
		System.out.println("c3의 값 : "+c3);
	}
}

출력 결과

피연산자들이 모두 정수 타입이고, long 타입이 있을 경우 모두 long 타입으로 변환 후에 연산을 수행한다. 따라서 연산의 산출 타입은 long 이다.

예) int + long -> long + long = long

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

예) int + double -> double + double = double

두 피연산자 중에서 하나를 실수로 바꾸어 주는 작업을 해야함

int int1 = 10;

double result3 = (int1*1.0) / int2;   //int1에 1.0을 곱하면 10.0이 되면서 실수가 됨

double result3 = (double)int1 / int2; //double로 강제 타입변환

double result3 = int1 / (double)int2; //double로 강제 타입변환

예제)

package sec04.exam01_arithmetic;

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);
		
		double result7 = v1 / (double)v2; //강제 타입변환
		System.out.println("result7 = "+ result7);
		
		double result8 = (v1*1.0) / v2; //1.0을 곱함으로써 실수로 변환
		System.out.println("result8 = "+ result8);
	}
}

출력 결과


산술 연산시 주의할 점

오버플로우(연산후의 산출값이 산출타입으로 표현할 수 없는 범위의 값인 경우)로 인해 잘못된 값이 산출되는 것을 방지해야 함

1. 리터럴을 사용할 경우 : 피연산자와 연산 후의 값이 저장될 수 있는 충분한 타입을 사용

2. 런타임시 입력된 값일 경우 : 산술 연산자를 직접 사용하지 않는 것이 좋다. (메소드를 작성해서 오버플로우를 미리 조사하고 예외 처리 / 정해진 범위의 값인 경우에는 값을 받아서 사용하고, 정해진 범위의 값이 아닌경우에는 에러발생시키도록(예외))

정확한 계산은 정수를 사용

정확하게 계산해야 할때는 부동소수점(실수) 타입(float,double)을 사용하지 않는것이 좋으며, 정수 연산으로 변경해서 계산하는 것이 좋다.

예제)

package sec04.exam01_arithmetic;

public class AccuracyExample1 
{
	public static void main(String[] args) 
	{
		double result1 = 7 * 0.1;
		System.out.println(result1);
		
		int apple = 1;
		double pieceUnit = 0.1;
		int number = 7;
		
		double result = apple - number*pieceUnit; //정확하게 0.7이 아니기 때문에 값이 제대로 나오지 않을것임
		
		System.out.println("사과 한개에서");
		System.out.println("0.7조각을 빼면");
		System.out.println(result + "조각이 남는다.");
	}
}

출력 결과

package sec04.exam01_arithmetic;

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 + "조각이 남는다.");
	}
}

출력 결과

NaN과 Infinity 연산을 조심

좌측 피연산자가 정수 타입인 경우 나누는 수인 우측 피연산자는 0을 사용할 수 없다. 만일 0으로 나누면 컴파일은 정상적으로 되지만, 실행시 예외가 발생한다. (예외처리를 해주어야함)

Double.isInfinite() : 값이 infinity값이면 true 리턴, 그렇지 않으면 false 리턴

Double.isNaN() : 값이 NaN이면 true 리턴, 그렇지 않으면 false 리턴

입력된 문자열을 숫자로 변환할 때  NaN인지 검사
package sec04.exam01_arithmetic;

public class InputDataCheckNanExample 
{

	public static void main(String[] args) 
	{
		String userInput = "NaN"; //유저에게 입력받은 값이라고 가정
		
		double val = Double.valueOf(userInput); //입력값을 double타입으로 변환
		
		double currentBanlance = 10000.0;
		//NaN과 10000.0을 더하고 출력할경우 NaN이 저장되어 기존의 데이터가 사라진다. 
		//따라서 사용자로부터 문자열을 입력 받을때 반드시 "NaN"인지 조사해야한다.
		if(Double.isNaN(val)) //받은 값이 NaN이라면
		{
			System.out.println("NaN값이 입력되어 처리할 수 없습니다."); //처리할수 없습니다. 문구 출력
			val = 0.0; //받은값을 0.0으로 만들어줌
		}
		currentBanlance = currentBanlance + val;
		System.out.println(currentBanlance);	
	}
}

출력 결과


문자열 연결 연산자(+)

피연산자 중 문자열이 있으면 문자열로 결합시킨다.

package sec04.exam02_string_concat;

public class StringConcatExample 
{
	public static void main(String[] args) 
	{
		String str1 = "JDK" + 6.0;
		String str2 = str1 + "특징";
		System.out.println(str1);
		System.out.println(str2);
		
		String str3 = "JDK" + 3 + 3.0;
		String str4 = 3 + 3.0 + "JDK"; //3 + 3.0 이 산술연산자로 먼저 계산 된 후에 JDK가 더해진것
		System.out.println(str3);
		System.out.println(str4);
	}
}

출력 결과

 

728x90