국비지원수업에서 배운 연산자에 대해서 이론적인 부분을 복습해보았다..
-------------------------------------------------------------------------------------------------------------------------------
[연산자의 종류]
- 연산을 할 때는 1) 우선순위, 2)자료형을 고려해야 한다.
우선순위 | 단항연산자 | 연산순서 | |
높음 | 최우선 연산자 | (괄호) | |
↓ | 단항연산자 | ~, !, ++, --, (cast), -(부호) | <-- |
산술연산자 | + , - , * , /(몫) , %(나머지) | --> | |
쉬프트 연산자 (=2진 연산자) |
>>, <<, >>> | --> | |
관계 연산자 | >, >=, <, <=, ==, != | --> | |
이진논리연산자 | &, ^, |, >> | --> | |
일반논리연산자 | &&(AND), ||(OR) | --> | |
삼항연산자 | (조건) ? 값(참) : 값(거짓) | <-- | |
대입연산자 | = | ||
낮음 | (복합 대입 연산자) | +=, -=, *=, /=, %=, &=, ^=, |=, >>=, <<= | <-- |
1. 단항 연산자 : ~, !, ++, --, (cast), -(부호)
> 단항의 앞에 사용하는 연산자이다.
(1) ~ (tilde) : 이진 논리 Not 연산자 (1의 보수)
//Tilde ~ : 2진수로 표현했을 때의 1의 보수
class Tilde{
public static void main(String[] args){
int n = 10;
System.out.printf("[%32s]\n",Integer.toBinaryString(n));
System.out.printf("[%32s]\n",Integer.toBinaryString(~n));
}
}
>> 결과
[ 1010]
[11111111111111111111111111110101]
(2) ! : 일반논리 Not연산자
class NotOperator{
public static void main(String[] args){
boolean bOk = !(3>2); //boolean bOk = !3>2; 는 불가 why? 일반논리일 경우에만 !사용 가능
//(3>2) == true
System.out.printf("!(3>2) : %b\n",bOk);
System.out.printf("!true : %b\n",!true);
}
}
>> 결과
!(3>2) : false
!true : false
(3) ++(증가), --(감소) : 증감 연산자
- 전위형 : ++n --> 산술연산, 명령이 있기 전에 먼저 변수값을 +1한다. (먼저 변수값을 +1)
- 후위형 : n++ --> 산술연산, 명령이 있은 후에 변수값을 +1한다. (마지막에 변수값을 +1)
public class PlusplusOperator {
public static void main(String[] args) {
int x = 1;
int y = 2;
int z;
z = ++x + y++;
System.out.printf("x : %d, y : %d, z : %d\n",x,y,z);
}
}
>> 결과
x : 2, y : 3, z : 4
//z = ++x + y++; 의 연산 순서
//1) ++x --- > x = x + 1; //2
//2) x + y --- > 2 + 2
//3) z = x + y --- > z = 4;
//4) y++ --- > y = y + 1; //3
(4) -(부호) : (-1)을 곱해주는 연산자
(5) 강제 형변환 연산자 : cast 연산자
Casting 1. 자동 형변환 1) 연산시 : 자료형이 큰 쪽으로 자동 형변환 2) 대입시 : '='를 기준으로 좌변항이 더 큰 자료형일 경우 좌변형의 자료형으로 자동 형변환 2. 강제 형변환 : '(자료형) 변수' 형식 **자동 형변환시, 프로모션(큰쪽으로 형변환)된다. **강제 형변환시, 디모션(작은쪽으로 형변환)이 가능하나, 오버플로우의 가능성을 염두해야한다. |
2. 산술연산자 : 사칙연산
- 사칙연산 시, 위의 Casting 방식에 따라 자동 형변환이 이루어짐.
** int보다 작은 정수형 자료형의 경우, 사칙연산 시 결과가 int형으로 나타남
ex. byte + byte = int
why? 중앙처리장치 안의 연산기(ALU)를 통해 연산이 이루어지는데, 계산 시 4byte단위로 결과를 냄
---> 결과적으로 int 타입으로 변환
3. 쉬프트연산자(=2진 연산자) : 2진수로 표현한 값에서 >>우측으로 가고, <<좌측으로 가기
- >> : 우측으로 가고, 앞쪽을 부호로 채우기
- << : 좌측으로 가고, 뒤쪽을 0으로 채우기
- >>> : 우측으로 가고, 앞쪽을 0으로 채우기
4. 관계연산자 : >, >=, <, <=, ==, !=
5. 이진논리연산자
package mymain;
public class _05_이진논리연산자 {
public static void main(String[] args) {
//5. 이진논리연산자
System.out.printf("[%32s]\n",Integer.toBinaryString(7));
System.out.printf("[%32s]\n",Integer.toBinaryString(5));
System.out.printf("[%32s]\n",Integer.toBinaryString(7&5));
System.out.printf("[%32s]\n",Integer.toBinaryString(7|5));
System.out.printf("[%32s]\n",Integer.toBinaryString(7^5));
// & ^ | >>의 활용 사례
int birthday = 0x19880815; //실제로 birthday일케 안씀... 4bit가 8개.. 32bit --> int 형
System.out.printf("생년월일 : %x\n",birthday); // 19880805 '0805'제외 하고자함
//출생년도 추출
int year = birthday >>> 16; // 16bit만큼 밀기 (16진수 하나당 4bit * 4), 앞 공간(부호영역) 양음수 상관없이 0으로 채워짐
System.out.printf("출생년도 : %x년\n",year);
//출생월 추출
//0x00198808
int month = birthday >>> 8 & 0x000000ff; //소거(0일때 거짓, 1일때 참. 0&0=0. 1&1=1 >> 1이 있는 쪽은 살아남)
System.out.printf("출생월 : %02x월\n",month);
//출생일 추출
int day = birthday & 0xff;
//int day = birthday & 0x000000ff;
System.out.printf("출생월 : %02x일\n",day);
//출생연월도에서 월을 수정 - 기존 : 0x19980815
//1. 월의 자리를 소거 (^) -- ^은 서로 배타적일 때 참(1), 그렇지 않으면 거짓(0) >> 1010과 1010은 같음 --> 0000이 됨
birthday = birthday ^ 0x0000800;
System.out.printf("생년월일 : %x\n",birthday);
//2. 추가하고 싶은 월 값 추가 (현재 : 0x19880015) 0 : 0000 5 : 0101
// | 0x00001100 1 : 0001 0 : 0000
// 0001 0101
birthday = birthday | 0x00001100; // |는 추가(0 또는 1 = 1 >> 1010 또는 1001은 1011)
System.out.printf("생년월일 : %x\n",birthday);
}
}
>> 결과
[ 111]
[ 101]
[ 101]
[ 111]
[ 10]
생년월일 : 19880815
출생년도 : 1988년
출생월 : 08월
출생월 : 15일
생년월일 : 19880015
생년월일 : 19881115
6. 일반논리연산자 : &&(AND), ||(OR)
- 일반논리연산자는 경제적 연산을 한다.
▼ 아래를 보면 경제적 연산을 하기 때문에 dead code 발생
class AndOr{
public staitc void main(String[] args){
System.out.println("----[&&]----");
System.out.printf("true && true : %b\n", (true && true));
System.out.printf("true && true : %b\n", (true && false));
System.out.printf("true && true : %b\n", (false && true)); //Alert : Dead Code
System.out.printf("true && true : %b\n", (false && false));//Alert : Dead Code
System.out.println("----[||]----");
System.out.printf("true || true : %b\n", (true || true)); //Alert : Dead Code
System.out.printf("true || true : %b\n", (true || false)); //Alert : Dead Code
System.out.printf("true || true : %b\n", (false || true));
System.out.printf("true || true : %b\n", (false || false));
}
}
- 일반논리연산자 예제 ) 윤년/평년 구하기
package mymain;
import java.util.Scanner;
public class _08_일반논리연산자응용2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
int year;
System.out.print("연도 : ");
year = scanner.nextInt();
//윤년/평년
//윤년 조건
//조건1. 400의 배수가 되는 해 (ex.400년, 800년...2000년)
//또는
//조건2. 4의 배수이면서 100의 배수가 아닌 해
if((/*조건 1*/year%400==0) || (/*조건2*/year%4==0 && year%100!=0)) {
System.out.printf("[%d]년도는 [윤년]입니다.\n",year);
}else {
System.out.printf("[%d]년도는 [평년]입니다.\n",year);
}
scanner.close();
}
}
>> 결과
연도 : 2022
[2022]년도는 [평년]입니다.
7. 삼항 연산자 : (조건) ? 값(참) : 값(거짓)
class threeOperator{
public static void main(String[] args){
int x = 10;
int y = 4;
String z;
z = (x % y ==0)? "맞다" : "아니다";
System.out.printf("%d는 %d의 배수가 %s", x, y, z);
}
}
>> 결과
10는 4의 배수가 아니다
8. 대입 연산자 : =
9. 복합 대입 연산자 : +=, -=, *=, /=, %=, &=, ^=, |=, >>=, <<=
int n;
n = 10;
n++; // n = n + 1;
n+=2; // n = n + 2;
n-=3; // n = n - 3;
----------------------------------------------------------------------------------------------------------------------------------
[연산자를 활용한 코드 예시]
1. 지폐/동전 갯수 세는 코드
- 산술연산자 /와 %를 활용했을 때에 계산이 간편해짐을 볼 수 있다.
package mymain;
import java.util.Scanner;
public class MoneyCnt {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
int input;
int tmp;
int[] moneyArr = {50000, 10000, 5000, 1000, 500, 100, 50, 10};
int[] cntArr = new int[9];
//사용자에게 금액 받기
System.out.print("금액 : ");
input = tmp = scanner.nextInt();
//화폐 갯수 세기 : 5만권부터 /와 % 연산자로 갯수 세기
for(int i = 0; i < moneyArr.length; i++) {
cntArr[i] = tmp / moneyArr[i];
tmp = tmp % moneyArr[i];
}
System.out.printf("---%d(원)에 대한 권종별 갯수---\n",input);
System.out.printf("50000원 : %d(매)\n",cntArr[0]);
System.out.printf("10000원 : %d(매)\n",cntArr[1]);
System.out.printf(" 5000원 : %d(매)\n",cntArr[2]);
System.out.printf(" 1000원 : %d(매)\n",cntArr[3]);
System.out.printf(" 500원 : %d(개)\n",cntArr[4]);
System.out.printf(" 100원 : %d(개)\n",cntArr[5]);
System.out.printf(" 50원 : %d(개)\n",cntArr[6]);
System.out.printf(" 10원 : %d(개)\n",cntArr[7]);
System.out.printf(" 1원 : %d(개)\n",cntArr[8]);
scanner.close();
}
}
>> 결과
금액 : 258439
---258439(원)에 대한 권종별 갯수---
50000원 : 5(매)
10000원 : 0(매)
5000원 : 1(매)
1000원 : 3(매)
500원 : 0(개)
100원 : 4(개)
50원 : 0(개)
10원 : 3(개)
1원 : 0(개)
2. 섭씨를 화씨로, 화씨를 섭씨로 변환하기
- 연산자를 사용할 때에 1) 연산 우선순위와 2) 자료형을 고려해야하는 이유를 볼 수 있다.
**잘못된 연산 순서와, 잘못된 자료형의 사용은 잘못된 결과를 나오게 함.
public class FarenCel {
public static void main(String[] args) {
// 온도변환
// 섭씨 -> 화씨 : F = 9/5 * C + 32;
// 화씨 -> 섭씨 : C = 5/9 *(F-32);
double cel = 7.0;
double far = 44.6;
FarenCel.toFar(cel);
FarenCel.toCel(far);
}
static void toFar(double cel) {
double result = (cel * 5/9) + 32;
//= (double *(int/int)) + int;
//= (double * double) + int;
//= double + int;
System.out.printf("섭씨 [%.1f] = 화씨 [%.1f]\n", cel, result);
}
static void toCel(double far) {
double result = (far - 32) * 5/9;
System.out.printf("화씨 [%.1f] = 섭씨 [%.1f]\n", far, result);
}
}
>> 결과
섭씨 [7.0] = 화씨 [35.9]
화씨 [44.6] = 섭씨 [7.0]
'Language > Java' 카테고리의 다른 글
[자바_복습] 중첩for문 활용_구구단/행렬/별찍기 (0) | 2022.03.11 |
---|---|
[자바_복습] 제어문 예시 - 조건문과 반복문 각각 (0) | 2022.03.08 |
[자바_복습] Scanner 입력 메서드 구분 (0) | 2022.03.04 |
[자바의 정석_복습] 객체지향 프로그래밍1(2) - 클래스(생성자, 초기화블럭) (0) | 2022.02.27 |
[자바의 정석_복습] 객체지향 프로그래밍1 - 클래스(변수,메서드) (0) | 2022.02.24 |