[이것이자바다] chapter 3. 연산자
chapter 3
연산자
연산자 종류 | 연산자 | 피연산자 수 | 산출값 | 기능 설명 | |||
---|---|---|---|---|---|---|---|
산술 | +,-,*,/,% | 이항 | 숫자 | 사칙연산 및 나머지 계산 | |||
부호 | +,- | 단항 | 숫자 | 음수와 양수의 부호 | |||
문자열 | + | 이항 | 문자열 | 두 문자열을 연결 | |||
대입 | =,+=,-=,*=,/=,%=,&=,^=,|=, «=,»=,»>= | 이항 | 다양 | 우변의 값을 좌변의 변수에 대입 | |||
증감 | ++, – | 단항 | 숫자 | 1만큼 증가/감소 | |||
비교 | ==,!=,>,<, >=, <=, instance of | 이항 | boolean | 값의 비교 | |||
논리 | !,&, | , &&, | 단항, 이항 | boolean | 논리적 NOT, AND, OR 연산 | ||
조건 | (조건식)?: A: B | 삼항 | 다양 | 참이면 A, 거짓이면 B | |||
비트 | ~, &, |, ^(xor) | 단항, 이항 | 숫자, boolean | 비트 NOT, AND, OR, XOR 연산 | |||
쉬프트 | », «, »> | 이항 | 숫자 | 비트를 좌측/우측으로 밀어서 이동 |
- 연산자의 우선순위는 연산의 수행을 의미하는 것이 아니다. 우선순위는 연산의 결합을 의미한다.
부호 연산자 +,-
- 부호 연산자를 사용할 때 주의할 점은 부호 연산자의 산출 타입이 int가 된다는 것이다. 예를 들어 short 타입 값을 부호 연산하면 int 타입으로 바뀐다.
byte a = 5;
short b = -a; (x) //원래 같은 경우는 자동형변환이 되지만 -연산자에 의해 a는 int가 되므로 컴파일 에러가 발생한다.
// 따라서 -a를 short로 Casting 해야 한다.
short b = (short)-a; (o)
증감 연산자 ++, –
연산식 | 설명 |
---|---|
++ a | 다른 연산을 수행하기 전에 a의 값을 1 증가시킴 |
– a | 다른 연산을 수행하기 전에 a의 값을 1 감소시킴 |
a ++ | 다른 연산을 수행한 후 a의 값을 1 증가시킴 |
a – | 다른 연산을 수행한 후 a의 값을 1 감소시킴 |
논리 부정 연산자 (!)
연산식 | 설명 |
---|---|
! result | (1)result 가 true 이면 false 값 산출,(2)result가 false 이면 true 값 산출 |
비트 반전 연산자 (~)
~ 연산자는 정수 타입(byte, short, int, long) 의 피연산자에만 사용되며, 피연산자를 2진수로 표현했을 때 비트값인 0을 1로, 1을 0으로 반전한다.
연산 후, 부호 비트인 최상위 비트(MSB)를 포함해서 모든 비트가 반전되므로, 부호도 반전된다.
- 자바의 정수값을 총 32비트의 이진 문자열로 리턴하는 메소드: integer.toBinaryString()
오버플로우& 언더 플로우
int x = 1000000; // 10^6
int y = 1000000; // 10^6
int z = x*y; // 10^12.. int의 가장 큰 수인 2^31-1을 초과... => 오버플로우 발생.
// 2^10 = 10^3 => 2^20 = 10^6 => 2^40 = 10^12
System.out.println(z); // => -72737996 오버플로우가 발생하여 쓰레기 값 발생.
산술 연산 전에 오버플로우를 탐지
public class OverflowSolution {
public static void main(String[] args) {
try {
int result1 = safeAdd(2000000000,2000000000);
System.out.println(result1);
}catch (ArithmeticException e){
System.out.println("1: 오버플로우가 발생하여 정확하게 계산할 수 없음.");
}
try {
int result2 = safeAdd(-2000000000, -2000000000);
System.out.println(result2);
}catch(ArithmeticException e) {
System.out.println("2: 오버플로우가 발생하여 정확하게 계산할 수 없음.");
}
}
private 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;
}
}
- 정확하게 계산할 때에는 부동소수점 타입을 사용하지 않는다.
=> 실수 타입 자체가 오차가 있는 타입이고 산술 연산시 실수 타입은 정확히 값을 연산하는 게 아니라 근사값을 연산하기 때문이다.
int apple = 1;
double pieceUnit = 0.1;
int number = 7;
double result = apple - pieceUnit*number; // 이때 piceUnit은 0.1이 아니라 0.1의 근사값으로 곱한다.
System.out.println(result); // 0.299999999999999999993 ==> 0.3이 아닌 오차가 있는 값 출력됨...
- 해결책 코드
int apple = 1;
int totalPieces = apple * 10 ;
int number = 7;
int temp = totalPieces - number;
double result = temp/10.0; ==> 부동소수점 아래에 있는 수가 아닌 10(=10.0)으로 나눔.
System.out.println(result); // 0.3으로 출력.
삼항 연산자
- 조건식 ? A : B => 조건식이 참이면 return A , 조건식이 거짓이면 return B.
이중 삼항 연산자 예제
import java.util.Scanner;
public class Conditional {
public static void main(String[] args) {
int score;
Scanner sc = new Scanner(System.in);
score = sc.nextInt();
char grade = (score > 90) ? 'A' : ((score >80) ? 'B':'C'); // score가 90을 넘기면 'A' 산출
System.out.println(grade); // 아니면 다시 오른쪽 삼항 연산자로 넘어가 80을 넘기면 'B' 아니면 'C' 산출.
}
}