연산자는 값을 계산하거나, 비교하거나, 바꾸는 데 쓰는 기호다.
이번 파트는 기호를 많이 외우는 것보다 값이 어떤 순서로 계산되는지, 타입이 다르면 어떻게 처리되는지, 증감 연산자가 언제 적용되는지를 이해하는 것이 더 중요하다.
연산자를 제대로 이해하면 뒤에서 배우는조건문,반복문도 훨씬 쉽게 읽힌다.
왜냐하면if는 비교와 논리를 쓰고,for는 증감 연산자를 계속 쓰기 때문이다.
개념
연산자는 값에 어떤 동작을 하는 기호다.
이때 연산의 대상이 되는 값을피연산자라고 한다.
예를 들어10 + 2에서+는 연산자이고,10과2는 피연산자다.
또++num처럼 값 하나만 대상으로 하는 연산자도 있고,a ? b : c처럼 여러 값을 함께 보는 연산자도 있다.
프로그램은 값을 단순히 저장만 하는 것이 아니라, 계산하고, 비교하고, 조건에 따라 고르고, 다시 저장하는 과정을 계속 반복한다.
연산자는 바로 이런 동작을 만들 때 쓰는 기본 도구다.
즉, 연산자는 단순한 기호가 아니라 값을 계산하고 판단하는 문법의 핵심이라고 보면 된다.
핵심 특징
(1) 연산자는 값을 계산할 때 쓴다.
(2) 연산자는 비교 결과를true,false로 만들기도 한다.
(3) 연산자는 값을 다시 변수에 저장할 때도 쓰인다.
(4) 뒤에서 배우는조건문,반복문도 결국 연산자와 함께 동작한다.
헷갈리기 쉬운 부분
연산자를 그냥 기호 목록으로만 보면 외우기 어렵다.
처음에는 “이 연산자가 무슨 일을 하는지” 중심으로 이해하는 것이 더 중요하다.
예를 들어
+: 더하기 또는 문자열 결합>: 크기 비교&&: 조건 두 개를 함께 판단=: 값을 저장처럼 역할부터 잡아두면 읽기가 훨씬 쉬워진다.
개념
연산자는 하는 일에 따라 여러 종류로 나눌 수 있다.
이번 2일차에서 주로 보게 되는 연산자는 아래와 같다.
.: 멤버 연산자++,--,!,(type),+,-: 단항 연산자*,/,%: 곱셈 계열 산술 연산자+,-: 덧셈 계열 산술 연산자>,<,>=,<=,==,!=: 비교 연산자&&,||,!: 논리 연산자? :: 삼항 연산자=,+=,-=,*=,/=,%=: 대입 연산자이렇게 나눠서 보면 연산자를 기능별로 정리할 수 있다.
즉, “값을 계산하는 연산자”, “참거짓을 판단하는 연산자”, “값을 저장하는 연산자”처럼 묶어서 보는 것이다.
핵심 특징
(1) 산술 연산자는 숫자를 계산한다.
예:+,-,*,/,%
(2) 비교 연산자는 값을 비교해서true,false를 만든다.
예:>,<,==,!=
(3) 논리 연산자는true,false를 다시 묶어서 판단한다.
예:&&,||,!
(4) 삼항 연산자는 조건에 따라 둘 중 하나를 고른다.
예:조건식 ? 값1 : 값2
(5) 대입 연산자는 값을 변수에 저장한다.
예:=,+=,-=
헷갈리기 쉬운 부분
+처럼 하나의 기호가 상황에 따라 역할이 달라지는 경우가 있다.
예를 들어 숫자끼리 만나면 덧셈이지만, 문자열과 만나면 결합이 된다.
또!는 논리 연산자이면서 동시에 피연산자 하나만 쓰는 단항 연산자이기도 하다.
즉, 분류 기준이 하나만 있는 것은 아니다는 점도 같이 알아두면 좋다.
개념
연산자는 피연산자가 몇 개 필요한지에 따라서도 나눌 수 있다.
여기서 말하는항은 연산의 대상이 되는 값이라고 보면 된다.
예를 들어10 + 2는 값 두 개가 필요하다.
반면++num은 값 하나만 있으면 된다.
이렇게 보면 연산자는 크게 세 가지로 나뉜다.
- 단항 연산자 : 피연산자 1개
- 이항 연산자 : 피연산자 2개
- 삼항 연산자 : 피연산자 3개
핵심 특징
(1) 단항 연산자는 값 하나만 대상으로 한다.
예:++,--,!,(type), 부호 연산자+,-
(2) 이항 연산자는 값 두 개를 대상으로 한다.
예:+,-,*,/,%,>,<,==,&&,||,=
(3) 삼항 연산자는 값 세 개를 대상으로 한다.
예:조건식 ? 값1 : 값2
(4) 보통 항의 개수가 적은 연산자가 우선순위가 더 높은 편이다.
코드 예제
++num; // 단항 연산자 num + 10; // 이항 연산자 num % 2 == 0 ? 1 : 0; // 삼항 연산자.
헷갈리기 쉬운 부분
+,-는 상황에 따라 단항 연산자일 수도 있고 이항 연산자일 수도 있다.
예를 들어-10 // 단항 연산자 10 - 3 // 이항 연산자처럼 같은 기호라도 쓰인 방식에 따라 달라진다.
개념
식 안에 연산자가 여러 개 들어가면 아무 순서로나 계산하지 않는다.
자바는 우선순위가 높은 것부터 계산한다.
이걸 알아야 하는 이유는 간단하다.
같은 식이라도 어느 부분을 먼저 계산하느냐에 따라 결과가 달라질 수 있기 때문이다.
예를 들어10 + 2 * 3이 식은 왼쪽부터
10 + 2를 먼저 하는 것이 아니라,
*가+보다 우선순위가 높기 때문에2 * 3이 먼저 계산된다.
그래서 결과는16이 된다.
즉, 연산자를 이해할 때는 기호의 뜻만 아는 것이 아니라 계산 순서까지 함께 이해해야 한다.
핵심 특징
(1) 보통 아래 흐름으로 생각하면 된다.
. → 단항 → 산술 → 비교 → 논리 → 삼항 → 대입(2)
*,/,%는+,-보다 먼저 계산된다.
(3) 산술 연산이 비교 연산보다 먼저 계산된다.
(4) 비교 연산이 논리 연산보다 먼저 계산된다.
(5) 대입 연산은 거의 마지막에 수행된다.
코드 예제
10 + 2 * 3 // 16 num % 2 == 1 // 먼저 num % 2, 그다음 == 1 num > 0 && num < 10 // 먼저 비교 두 개, 그다음 &&.
헷갈리기 쉬운 부분
우선순위를 전부 외우려고 하면 오히려 더 헷갈린다.
처음에는 아래 흐름만 확실히 잡아두면 된다.
- 산술이 비교보다 먼저
- 비교가 논리보다 먼저
- 대입은 거의 마지막
그리고 식이 복잡하면 괄호를 쓰는 것이 가장 안전하다.
괄호는 계산 순서를 바꾸기도 하지만, 사람이 읽기 쉽게 만들어주는 역할도 한다.
개념
산술 연산자는 숫자를 계산할 때 쓰는 연산자다.
+: 더하기-: 빼기*: 곱하기/: 나누기%: 나머지이 중에서 특히 중요한 것은
/와%다.
정수 나눗셈과 나머지 연산은 뒤에서도 계속 나온다.
핵심 특징
(1) 정수끼리 나누면 결과도 정수다.
(2) 정수 나눗셈에서는 소수점 아래가 버려지고 몫만 남는다.
(3)%는 나머지를 구하는 연산자다.
(4)%는 홀수/짝수 판단, 배수 판별에 자주 쓰인다.
코드 예제
예제:
OperTest2int num1 = 5; int num2 = 3; System.out.println(num1 + num2); System.out.println(num1 - num2); System.out.println(num1 * num2); System.out.println(num1 / num2); System.out.println((double)num1 / num2); System.out.println(num1 % num2); // 출력결과 // 8 // 2 // 15 // 1 // 1.6666666666666667 // 2이 코드는 같은 숫자라도 연산자에 따라 결과가 달라진다는 점을 보여준다.
특히num1 / num2는 둘 다int이므로 결과가1이다.
반대로(double)num1 / num2는 먼저 실수형으로 바꿔 계산하기 때문에 소수점까지 나온다.
num1 % num2는5를 3으로 나눈 나머지라서2가 된다.
헷갈리기 쉬운 부분
5 / 3이1.666...이 아니라1이 되는 이유는 정수끼리 계산했기 때문이다.
정수끼리 나누면 자바는 소수점 아래를 남기지 않는다.
그래서 소수점까지 필요한 계산이라면, 계산하기 전에 한쪽을 실수형으로 바꿔야 한다.
+ 연산자와 문자열 결합개념
+는 가장 자주 쓰는 연산자지만, 상황에 따라 의미가 달라진다.
숫자와 숫자를+하면 덧셈이 된다.
하지만 문자열이 끼어들면 계산이 아니라 문자열을 이어 붙이는 결합이 된다.
즉, 같은+라도 어떤 값과 함께 쓰느냐에 따라 역할이 달라진다.
핵심 특징
(1) 숫자끼리
+하면 덧셈이다.
(2) 문자열이 하나라도 있으면, 그 뒤부터는 문자열 결합으로 처리된다.
(3) 계산은 기본적으로 왼쪽에서 오른쪽으로 진행된다.
(4) 괄호가 있으면 괄호 안이 먼저 계산된다.
코드 예제
예제:
OperTest1int result1 = 10 + 2 + 8; System.out.println("result1: " + result1); String result2 = 10 + 2 + "8"; System.out.println("result2: " + result2); String result3 = 10 + "2" + 8; System.out.println("result3: " + result3); String result4 = "10" + 2 + 8; System.out.println("result4: " + result4); String result5 = "10" + (2 + 8); System.out.println("result5: " + result5); // 출력결과 // result1: 20 // result2: 128 // result3: 1028 // result4: 1028 // result5: 1010이 코드는
+가 숫자 계산일 때와 문자열 결합일 때 결과가 어떻게 달라지는지 보여준다.
10 + 2 + 8은 숫자끼리 계산하므로2010 + 2 + "8"은 앞에서12가 만들어진 뒤"8"과 붙어서"128""10" + 2 + 8은 처음부터 문자열이 있으므로"1028""10" + (2 + 8)은 괄호 안이 먼저 계산되어"1010"
헷갈리기 쉬운 부분
"10" + 2 + 8과"10" + (2 + 8)은 결과가 다르다.
"10" + 2 + 8→"1028""10" + (2 + 8)→"1010"겉보기에는 비슷하지만,
하나는 왼쪽부터 문자열 결합이 이어지고,
다른 하나는 괄호 안 덧셈이 먼저 끝난다.
Math.random()과 난수 공식개념
Math.random()은 난수를 만들어주는 기능이다.
이 값은0.0 이상 1.0 미만의 실수로 나온다.
즉,0.000...은 나올 수 있지만1.0은 나오지 않는다.
그래서 원하는 범위의 정수 난수가 필요하면, 이 값을 가공해서 사용해야 한다.
핵심 특징
(1)
Math.random()의 기본 범위는0 <= r < 1이다.
(2) 여기에 어떤 수를 곱하면 범위가 그만큼 커진다.
(3)int로 형변환하면 소수점 아래가 잘리고 정수만 남는다.
(4) 마지막에 시작값을 더하면 원하는 범위로 옮길 수 있다.
원하는 범위의 정수 난수 공식
정수 난수를 만들 때는 아래 공식을 기억하면 된다.
(int)(Math.random() * (마지막값 - 시작값 + 1)) + 시작값이 공식에서
(마지막값 - 시작값 + 1)은 개수- 마지막
+ 시작값은 시작 위치 보정역할을 한다.
예를 들어1 ~ 3난수를 만들고 싶다면,
필요한 숫자는1, 2, 3으로 총 3개다.
그래서 식은 이렇게 된다.(int)(Math.random() * 3) + 1흐름은 아래와 같다.
Math.random()→0.0 이상 1.0 미만* 3→0.0 이상 3.0 미만int형변환 →0, 1, 2+ 1→1, 2, 3같은 방식으로 보면 다음과 같다.
1 ~ 10 → (int)(Math.random() * 10) + 1 1 ~ 45 → (int)(Math.random() * 45) + 1 3 ~ 10 → (int)(Math.random() * 8) + 3 30 ~ 40 → (int)(Math.random() * 11) + 30.
코드 예제
예제:
OperTest3double r_num = Math.random(); System.out.println(r_num); double r_num2 = r_num * 10; System.out.println(r_num2); int r_num3 = (int)r_num2; System.out.println(r_num3); System.out.println(r_num3 + 1); // 출력결과 예시 // 0.731245... // 7.31245... // 7 // 8이 코드는 난수가 만들어지고, 범위가 커지고, 정수로 바뀌고, 마지막에 시작값이 보정되는 흐름을 단계별로 보여준다.
헷갈리기 쉬운 부분
아래 두 식은 완전히 다르다.
(int)(Math.random() * 10) (int)Math.random() * 10첫 번째는
0 ~ 9가 나오지만,
두 번째는Math.random()을 먼저int로 바꿔버려서 항상0만 나온다.
즉, 곱한 뒤에 형변환해야 한다.
++, --개념
증감 연산자는 값을 1 증가시키거나 1 감소시키는 연산자다.
++: 1 증가--: 1 감소이 연산자는 단항 연산자이고, 변수에만 사용할 수 있다.
즉, 값 자체를 바꾸는 것이 아니라 변수에 들어 있는 값을 바꾸는 연산자다.
핵심 특징
(1)
++num은 먼저 증가시키고 사용한다.
(2)num++은 먼저 사용하고 나중에 증가시킨다.
(3)--num,num--도 원리는 같다.
(4) 하지만 단독 문장으로 쓰이면 앞에 쓰든 뒤에 쓰든 차이가 없다.
코드 예제
예제:
OperTest4int num = 10; System.out.println(num); System.out.println(++num); System.out.println(++num); System.out.println(++num); System.out.println(num++); System.out.println(num++); System.out.println(num); System.out.println(--num); System.out.println(num); // 출력결과 // 10 // 11 // 12 // 13 // 13 // 14 // 15 // 14 // 14앞에 붙은
++num은 먼저 값을 1 증가시킨 뒤 출력한다.
그래서10다음에 바로11,12,13이 나온다.
반대로num++은 현재 값을 먼저 출력한 뒤, 그다음에 값이 1 증가한다.
그래서 화면에는13,14가 출력되지만 내부 값은 이미 증가한 상태가 된다.
헷갈리기 쉬운 부분
아래처럼 단독으로 쓰면 차이가 없다.
num++; ++num;둘 다 그냥
num을 1 증가시키는 문장이다.
다른 연산과 엮이지 않았기 때문에 “먼저”와 “나중에”의 차이가 드러나지 않는다.
반대로 대입이나 출력과 함께 쓰이면 차이가 생긴다.
개념
증감 연산자는 대입과 함께 쓰면 차이가 더 분명하게 드러난다.
이때는 값이 언제 바뀌는지를 정확히 봐야 한다.
코드 예제
예제:
OperTest7int su1 = 10; int su2 = ++su1; System.out.println(su1); System.out.println(su2); int su3 = su1++; System.out.println(su1); System.out.println(su3); // 출력결과 // 11 // 11 // 12 // 11
int su2 = ++su1;은su1을 먼저 1 증가시킨 뒤 그 값을su2에 넣는다.
그래서 둘 다11이 된다.
반대로int su3 = su1++;은 현재su1값을 먼저su3에 넣고,
그다음su1을 증가시킨다.
그래서su3는11,su1은12가 된다.
헷갈리기 쉬운 부분
눈으로 보면 비슷하지만 결과는 다르다.
++su1: 먼저 증가su1++: 먼저 사용이 차이를 이해하지 못하면 나중에 복잡한 식에서 결과를 자주 틀리게 된다.
개념
비교 연산자는 두 값을 비교해서
true또는false를 만드는 연산자다.
>: 크다<: 작다>=: 크거나 같다<=: 작거나 같다==: 같다!=: 다르다즉, 비교 연산자는 계산 결과를 숫자로 만드는 것이 아니라 참과 거짓으로 만든다.
핵심 특징
(1) 비교 연산의 결과는 항상
boolean이다.
(2) 숫자뿐 아니라 문자도 비교할 수 있다.
(3) 문자는 내부적으로 숫자값을 가지고 있어서 크기 비교가 가능하다.
(4) 문자열 비교는==가 아니라equals()를 써야 한다.
코드 예제
예제:
OperTest11int 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); // 출력결과 // result1: true // result2: false // result3: true이 코드는 비교 연산 결과가
true,false로 나온다는 점을 보여준다.
헷갈리기 쉬운 부분
문자도 비교할 수 있다.
char char1 = 'A'; char char2 = 'B'; boolean result4 = (char1 < char2); System.out.println(result4); // 출력결과 // true
'A'와'B'는 글자처럼 보이지만 내부적으로는 숫자값을 가진다.
그래서'A' < 'B'같은 비교도 가능하다.
또 문자열은 아래처럼 비교해야 한다.String str1 = "자바"; String str2 = "Java"; System.out.println(str1.equals(str2));문자열은 내용 비교를 할 때
equals()를 사용한다.
&&, ||, !개념
논리 연산자는
true,false를 다시 조합하는 연산자다.
&&: 둘 다 참일 때만 참||: 하나라도 참이면 참!: 참과 거짓을 뒤집음이 연산자들은 조건문에서 아주 자주 쓰인다.
특히&&,||는 오른쪽 식을 아예 검사하지 않을 수도 있다.
핵심 특징
(1)
&&는 앞이 이미 거짓이면 뒤를 보지 않는다.
(2)||는 앞이 이미 참이면 뒤를 보지 않는다.
(3)!는 참이면 거짓으로, 거짓이면 참으로 바꾼다.
(4) 이렇게 불필요한 계산을 건너뛰는 것을short-circuit라고 볼 수 있다.
코드 예제
예제:
OperTest12int num = 100; System.out.println(num > 100 && ++num == 101); System.out.println(num); System.out.println(num > 100 || ++num == 101); System.out.println(num); // 출력결과 // false // 100 // true // 101첫 번째 식은
num > 100이 이미 거짓이므로,&&뒤쪽은 볼 필요가 없다.
그래서++num == 101은 실행되지 않고num은 그대로100이다.
두 번째 식은num > 100이 거짓이기 때문에,||는 오른쪽까지 확인한다.
그래서++num == 101이 실행되고,num은101이 된다.
헷갈리기 쉬운 부분
식 안에
++num이 있다고 해서 무조건 값이 증가하는 것은 아니다.
논리 연산자가 뒤쪽 식을 평가하지 않으면, 그 증가도 일어나지 않는다.
이 부분은 초보자가 자주 틀리는 포인트다.
즉,&&,||는 참거짓만 결정하는 것이 아니라 뒤쪽 식이 실제로 실행될지도 결정한다.
&와 |, &&와 ||의 차이개념
조건식에서 자주 보는 것은
&&,||지만,
코드에서는&,|도 볼 수 있다.
지금 단계에서는 아래 차이만 알고 있으면 된다.
&&,||: 앞의 결과에 따라 뒤를 안 볼 수 있다.&,|: 양쪽을 모두 본다고 이해하면 된다.
코드 예제
예제:
OperTest10int charCode = 'A'; if (65 <= charCode & charCode <= 90) { System.out.println("대문자이군요."); } if (97 <= charCode && charCode <= 122) { System.out.println("소문자이군요."); }이 코드는 문자 코드 범위를 이용해서 대문자인지, 소문자인지 검사한다.
'A'는 숫자로 보면65이므로 첫 번째 조건은 참이 된다.
그래서"대문자이군요."가 출력된다.
헷갈리기 쉬운 부분
지금은 조건식에서는
&&,||를 더 자주 쓴다고 생각하면 된다.
특히 오른쪽 식을 굳이 검사하지 않아도 되는 상황에서는&&,||가 더 효율적이다.
? :개념
삼항 연산자는 피연산자가 세 개인 연산자다.
형태는 아래와 같다.조건식 ? 값1 : 값2조건식이 참이면
값1, 거짓이면값2를 선택한다.
즉, 두 값 중 하나를 고르는 연산자다.
핵심 특징
(1) 첫 번째 자리에는 반드시 조건식이 와야 한다.
(2) 조건식 결과가true면 앞의 값을 고른다.
(3)false면 뒤의 값을 고른다.
(4) 결과가 하나의 값으로 나오므로 대입이나 출력에 바로 쓸 수 있다.
코드 예제
예제:
OperTest5int num = (int)(Math.random() * 10) + 1; char result = num % 2 == 1 ? '홀' : '짝'; System.out.println(num + "은 " + result + "수입니다."); System.out.printf("%d은 %c수입니다.\n", num, result); System.out.println(num + "은 " + (num % 2 == 1 ? '홀' : '짝') + "수입니다."); // 출력결과 예시 // 7은 홀수입니다. // 7은 홀수입니다. // 7은 홀수입니다.이 코드는 1부터 10 사이 난수를 하나 만든 뒤, 그 수가 홀수인지 짝수인지 판별해서
홀또는짝을 고른다.
num % 2 == 1이 참이면홀, 거짓이면짝이 선택된다.
자주 쓰는 공식
num % 2 == 0 // 짝수 num % 2 != 0 // 홀수 num % 2 == 1 // 홀수(양의 정수 기준에서 자주 사용)이 공식은 삼항 연산자와 같이 자주 쓰인다.
예를 들어num % 2 == 1 ? '홀' : '짝'은
num이 홀수면'홀', 짝수면'짝'을 선택하라는 뜻이다.
System.out.printf()도 함께 나오지만, 여기서는 출력 형식 자체보다 삼항 연산자로홀과짝중 하나를 선택하는 과정이 더 중요하다.printf는 3일차에서 더 자세하게 다룬다.
헷갈리기 쉬운 부분
삼항 연산자를 문자열 결합과 함께 바로 쓰면 괄호가 필요할 때가 많다.
num + "은 " + (num % 2 == 1 ? '홀' : '짝') + "수입니다."이렇게 괄호를 써주면
삼항 연산자 부분이 먼저 하나의 값으로 정리된 뒤 문자열과 결합된다.
개념
복합 대입 연산자는 계산과 대입을 한 번에 줄여서 쓰는 방식이다.
+=-=*=/=%=짧게 쓰여 있어서 편하지만, 실제로는 오른쪽 계산을 한 뒤 다시 왼쪽 변수에 저장하는 것과 같다.
핵심 특징
(1)
a += b는a = a + b와 같다.
(2)a -= b는a = a - b와 같다.
(3)a *= b는a = a * b와 같다.
(4)a /= b는a = a / b와 같다.
(5)a %= b는a = a % b와 같다.
풀어서 보면 이렇게 된다
result += 10; // result = result + 10; result -= 5; // result = result - 5; result *= 3; // result = result * 3; result /= 5; // result = result / 5; result %= 3; // result = result % 3;즉, 복합 대입 연산자는 새로운 특별한 연산이 아니라 기존 대입문을 짧게 줄여 쓴 형태다.
코드 예제
예제:
OperTest13int 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이 코드는
result값을 계속 바꾸면서 복합 대입 연산자가 어떻게 동작하는지 보여준다.
흐름을 풀어 쓰면 아래와 같다.
result = 0result = result + 10→10result = result - 5→5result = result * 3→15result = result / 5→3result = result % 3→0
헷갈리기 쉬운 부분
result += 10을 보면
그냥 “10을 더한다” 정도로만 보기 쉽다.
하지만 실제로는 아래 순서다.
1. 현재result값을 꺼낸다.
2.10을 더한다.
3. 그 결과를 다시result에 저장한다.즉, 읽기 → 계산 → 다시 저장 흐름이다.
여기부터는 앞에서 배운 연산자들이 실제 코드에서 어떻게 함께 쓰이는지 보는 단계다.
단순히 연산자 하나만 보는 것이 아니라, 여러 개가 섞였을 때 어떻게 읽는지가 중요하다.
문제에서 무엇을 하려는지
산술, 비교, 논리 연산자를 한 코드 안에서 한꺼번에 확인하는 예제다.
각 연산이 어떤 결과를 만드는지, 그리고 논리 연산에서 오른쪽 식이 언제 실행되는지를 같이 볼 수 있다.
이 예제에서 사용된 개념
- 산술 연산자
- 비교 연산자
- 논리 연산자
- 나머지 연산자
- 증감 연산자
short-circuit
코드 예제
예제:
OperTest6int num1 = 100, num2 = 50; System.out.println(num1 + num2); System.out.println(num1 - num2); System.out.println(num1 * num2); System.out.println(num1 / num2); System.out.println(num1 % num2); System.out.println(num1 > num2); System.out.println(num1 < num2); System.out.println(num1 == num2); System.out.println(num1 != num2); System.out.println(num1 > 0 && num2 > 0); System.out.println(num2 > 50 && ++num1 == 101); System.out.println(num1); // 출력결과 일부 // 150 // 50 // 5000 // 2 // 0 // true // false // false // true // true // false // 100코드 흐름
num1은100,num2는50이다.
앞부분은 산술 연산 결과를 그대로 확인하는 부분이다.
뒤쪽의num2 > 50 && ++num1 == 101이 핵심이다.
num2 > 50은50 > 50이라 거짓이다.
그러면&&오른쪽은 볼 필요가 없어서++num1 == 101은 실행되지 않는다.
그래서 마지막에 출력한num1은101이 아니라100그대로다.
헷갈리기 쉬운 부분
식 안에
++num1이 들어 있어도,
앞의 조건이 이미 거짓이면 실행되지 않을 수 있다.
++num과 num++ 차이 다시 확인하기문제에서 무엇을 하려는지
증감 연산자가 대입과 함께 쓰일 때 결과가 어떻게 달라지는지 확인하는 예제다.
이 예제에서 사용된 개념
- 전위 증가
- 후위 증가
- 대입 연산자
코드 예제
예제:
OperTest7int su1 = 10; int su2 = ++su1; System.out.println(su1); System.out.println(su2); int su3 = su1++; System.out.println(su1); System.out.println(su3); // 출력결과 // 11 // 11 // 12 // 11코드 흐름
++su1은 먼저 값을 증가시키고 그 값을 사용한다.
그래서su1,su2모두11이 된다.
su1++은 현재 값을 먼저 사용하고 나중에 증가시킨다.
그래서su3는11,su1은12가 된다.
헷갈리기 쉬운 부분
이 차이는 대입이나 출력처럼 다른 연산과 함께 쓸 때만 드러난다.
단독으로 쓰면 둘 다 그냥 1 증가다.
문제에서 무엇을 하려는지
증감 연산자를 단독으로 쓸 때와 대입과 함께 쓸 때 차이를 정리하는 예제다.
코드 예제
예제:
OperTest9int num = 100; num++; System.out.println(num); ++num; System.out.println(num); --num; System.out.println(num); num--; System.out.println(num); // 출력결과 // 101 // 102 // 101 // 100코드 흐름
여기서는 증감 연산자가 단독 문장으로 쓰였다.
이 경우에는 앞에 붙든 뒤에 붙든 차이가 없고, 그냥 값만 바뀐다.
헷갈리기 쉬운 부분
num++;와++num;는
다른 연산과 함께 쓰일 때만 차이가 난다.
단독 문장에서는 둘 다 그냥num을 1 증가시키는 문장이다.
문제에서 무엇을 하려는지
문자를 숫자로 보고 범위 검사하는 예제다.
동시에&,&&,|,||,!가 어떻게 쓰이는지도 함께 볼 수 있다.
이 예제에서 사용된 개념
- 문자 코드 비교
- 논리 연산자
- 나머지 연산자
- 부정 연산자
!
코드 예제
예제:
OperTest10int charCode = 'A'; if (65 <= charCode & charCode <= 90) { System.out.println("대문자이군요."); } int value = 6; 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의 배수가 아니군요."); }코드 흐름
'A'는 숫자로 보면65다.
그래서65 <= charCode && charCode <= 90 형태로 검사하면 대문자 범위에 들어간다는 것을 알 수 있다.value = 6은2의 배수이기도 하고3의 배수이기도 하다. 그래서2 또는 3의 배수이군요.`가 출력된다.
자주 쓰는 공식
65 <= charCode && charCode <= 90 // 대문자 범위 97 <= charCode && charCode <= 122 // 소문자 범위 value % 2 == 0 // 짝수 value % 3 == 0 // 3의 배수.
헷갈리기 쉬운 부분
문자도 내부적으로는 숫자로 다뤄질 수 있다.
그래서 문자 범위 검사도 결국 숫자 비교처럼 읽으면 된다.
문제에서 무엇을 하려는지
숫자, 문자, 실수, 문자열 비교를 한 번에 확인하는 예제다.
이 예제에서 사용된 개념
- 비교 연산자
- 문자 비교
- 실수 비교
- 문자열 비교
코드 예제
예제:
OperTest11float 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); // 출력결과 // result6: false // result7: true.
코드 흐름
겉보기에는 둘 다
0.1처럼 보여도
float와double은 저장 방식이 다르기 때문에 비교 결과가 다를 수 있다.
그래서num5 == num6은false가 나오고,
같은 쪽으로 맞춘 뒤 비교한num5 == (float)num6은true가 된다.
헷갈리기 쉬운 부분
실수는 눈에 보이는 값만 같다고 해서 항상 같은 값으로 비교되는 것은 아니다.
또 문자열은==가 아니라equals()로 비교해야 한다.
문제에서 무엇을 하려는지
&&,||가 뒤쪽 식을 실제로 실행하는지 확인하는 예제다.코드 예제
예제:
OperTest12int num = 100; System.out.println(num > 100 && ++num == 101); System.out.println(num); System.out.println(num > 100 || ++num == 101); System.out.println(num); // 출력결과 // false // 100 // true // 101.
코드 흐름
첫 번째는 왼쪽이 거짓이므로 오른쪽 식이 실행되지 않는다.
두 번째는 왼쪽이 거짓이어서 오른쪽을 검사하게 된다.
헷갈리기 쉬운 부분
논리 연산자는 단순히
true,false만 정하는 것이 아니라
오른쪽 식이 실제로 실행될지도 결정한다.
문제에서 무엇을 하려는지
복합 대입 연산자가 실제로는 어떻게 계산되는지 단계별로 보는 예제다.
이 예제에서 사용된 개념
- 대입 연산자
- 복합 대입 연산자
- 누적 계산
코드 예제
예제:
OperTest13int 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.
계산 공식 또는 풀이 원리
이 코드는 아래처럼 풀어 읽으면 된다.
result = 0; result = result + 10; result = result - 5; result = result * 3; result = result / 5; result = result % 3;즉, 매번 현재 값을 다시 꺼내 계산하고,
그 결과를 자기 자신에게 다시 넣는 구조다.
헷갈리기 쉬운 부분
복합 대입 연산자는 짧아서 편하지만,
실제로는 항상 현재 값 사용 → 계산 → 다시 저장 흐름으로 읽어야 한다.
- 연산자는 기능별로도 나뉘고, 항의 개수로도 나뉜다.
- 식 안에 연산자가 여러 개 있으면 우선순위에 따라 계산된다.
+는 덧셈일 수도 있고 문자열 결합일 수도 있다.- 정수끼리 나누면 소수점은 버려지고 몫만 남는다.
- 타입이 다르면 계산 전에 타입을 맞춘다.
Math.random()은0 이상 1 미만의 실수를 만든다.- 정수 난수 공식은
(int)(Math.random() * (마지막값 - 시작값 + 1)) + 시작값
형태로 만든다.++num과num++는 값이 바뀌는 시점이 다르다.&&,||는 오른쪽 식을 아예 실행하지 않을 수도 있다.- 삼항 연산자는 조건에 따라 값 하나를 고르는 연산자다.
- 복합 대입 연산자는 줄여 쓴 대입문일 뿐이고, 풀어 쓰면 더 이해하기 쉽다.
개념
연산은 값을 계산해서 하나의 결과를 만드는 과정이다.
그런데 계산하려는 두 값의 타입이 서로 다르면, 자바는 그대로 계산하지 않고 먼저 타입을 맞춘 뒤 연산하려고 한다.
예를 들어 한쪽은int, 다른 한쪽은double이면 저장 방식이 다르다.
int는 정수만 저장하고,double은 소수점까지 저장한다.
이 둘을 같은 기준 없이 바로 계산하면 결과를 어떤 타입으로 처리해야 할지 애매해진다.
그래서 자바는 연산 전에 두 값을 같은 타입 계열로 맞춘 뒤 계산한다.
이렇게 연산 과정에서 자바가 자동으로 타입을 맞춰주는 것을자동 형변환또는산술 변환이라고 한다.
반대로 개발자가 직접 타입을 바꾸고 싶을 때는 형변환 연산자를 사용한다.
이때는(double),(int)처럼 바꾸고 싶은 타입을 괄호로 적어서 값을 원하는 타입으로 바꾼다.
형변환이 중요한 이유는 결과가 달라질 수 있기 때문이다.
특히 나눗셈에서는 형변환을 언제 하느냐에 따라 소수점이 살아 있기도 하고, 이미 잘려 나가기도 한다.
즉, 이 부분에서 중요한 것은
타입이 다르면 자바가 먼저 타입을 맞춘다,
그리고 필요하면 개발자가 직접 형변환할 수도 있다는 점이다.
핵심 특징
(1) 타입이 다르면 계산 전에 타입을 맞춘다.
(2) 정수형과 실수형이 만나면, 정수형이 실수형으로 바뀐 뒤 계산된다.
(3)byte,short,char처럼int보다 작은 정수형도 연산할 때는 보통int로 바뀐다.
(4) 개발자가 직접 타입을 바꾸고 싶을 때는 형변환 연산자를 사용한다.
(5)boolean은 숫자형과 서로 형변환할 수 없다.
코드 예제
예제:
OperTest2int num1 = 5; int num2 = 3; System.out.println(num1 / num2); System.out.println((double)num1 / num2); double num3 = 5.0; System.out.println(num3 / num2); // 출력결과 // 1 // 1.6666666666666667 // 1.6666666666666667이 코드는 형변환이 결과를 어떻게 바꾸는지 보여준다.
num1 / num2는 둘 다int이므로 정수 나눗셈이 되어1이 나온다.
반면(double)num1 / num2는num1을 먼저double로 바꾼 뒤 계산하므로 소수점까지 살아 있는 결과가 나온다.<br/
또num3 / num2처럼 처음부터double과int가 함께 있으면,
int가double로 자동 형변환된 뒤 계산된다.
헷갈리기 쉬운 부분
형변환은 어디에 붙이느냐가 중요하다.
(double)num1 / num2이렇게 쓰면 나누기 전에
num1이double로 바뀌기 때문에 소수점까지 계산된다.
반대로(double)(num1 / num2)이렇게 쓰면
num1 / num2가 먼저 정수 나눗셈으로 끝난 뒤, 그 결과를double로 바꾼다.
그러면 이미 소수점은 사라진 뒤라서 결과는1.0이 된다.
즉, 늦게 바꾸면 이미 잘린 소수점은 돌아오지 않는다.
개념
대입 연산자
=는 오른쪽 값을 왼쪽 변수에 저장하는 연산자다.
이때 왼쪽은 값을 담을 공간이어야 하고, 오른쪽은 저장할 값이어야 한다.
즉,
- 왼쪽 : 저장할 공간
- 오른쪽 : 저장할 값
구조라고 보면 된다.
핵심 특징
(1) 타입이 같으면 바로 대입할 수 있다.
(2) 작은 범위의 값을 큰 범위 변수에 넣는 것은 보통 가능하다.
(3) 큰 범위 값을 작은 범위 변수에 넣으려면 형변환이 필요하다.
(4)boolean은 숫자형과 서로 형변환할 수 없다.
코드 예제
예제:
OperTest8int iv = 100; char cv = (char)iv; double dv = iv; // boolean bv = (boolean)iv; System.out.println(iv); System.out.println(cv); System.out.println(dv); // 출력결과 // 100 // d // 100.0
iv는int형 변수다.
이 값을double변수에 넣는 것은 가능하므로100.0으로 저장된다.
하지만char는int보다 표현 범위가 작기 때문에 그냥은 넣을 수 없어서(char)형변환이 필요하다.
100을 문자 코드로 해석하면d가 된다.
boolean은 숫자형과 성격이 다르기 때문에 형변환 자체가 되지 않는다.
헷갈리기 쉬운 부분
char cv = iv;는 안 되는데
double dv = iv;는 된다.
이 차이는 타입의 범위와 성격이 다르기 때문이다.
int → double: 가능int → char: 형변환 필요int → boolean: 불가능즉, 자바는 타입을 엄격하게 맞춰서 처리한다.