[자바]/자바의 정석 - 3판

Chapter03. 연산자

쿠릉쿠릉 쾅쾅 2021. 8. 26. 15:04
728x90

연산자 종류

종류 연산자  
산술 연산자 +,  -,  *,  /,  %,  <<,  >>  
비교 연산자 >,  <,  >=,  <=,  ==,  !=  
논리 연산자 &&,  ||,  !,  &,  |,  ^,  ~  
대입 연산자 =  
기타 (type),  ?:,  instanceof 형변환 연산자, 삼항연산자, insetanceof 연산자

 

 

연산자의 종류와 우선순위

 

 

 

더보기
  • 산술 > 비교 > 논리 > 대입.     대입은 제일 마지막에 수행됨
  • 단항(1) > 이항(2) > 삼항(3).    단항 연산자가 제일 우순선위 높음
  • 단항 연산자와 대입 연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽임

 

 

 

 

증감 연산자

  • 증가 연산자(++) : 피연산자의 값을 1 증가시킴
  • 감소 연산자(--) : 피연산자의 값을 1 감소시킴

증감 연산자의 전위형과 후위형

 

 

 

 

형변환 연산자

변환 수식 결과
int → char (char)65 'A'
char → int (int)'A' 65
float → int (int)1.6f 1
int → float (float)10 10.0f

 

 

 

 

 

자동 형변환

// 자동 형변환
byte b = 100;  // byte 타입의 범위 (-128 ~ 127)의 값 대입시 자동 형변환됨 


// 수동 형변환
int i = 100;
int j = 100;
byte c = i;  // 에러. int 타입의 변수를 byte 타입에 대입시 오류가 남 
byte c = (byte)j; // ok. byte 타입으로 형변환해서 대입해야함




// ex.1
char c1 = 'a';  // c1에 문자 'a' 코드 값인 97이 저장됨
char c2 == 'c1';  // c1에 저장되어 있는 값을 c2에 저장
char c3 == ' ';  // c3 를 공백으로 초기화

int i = c1 + 1;  // 'a' + 1  →  97+1  → 98

// c1 + 1 의 결과 값이 int 타입이기 때문에 char형 변수 c3에 담기 위해선 char 형으로 형변환이 필요함
c3 = (char)(c1 + 1);

c2++;  // c2++ 는 형변환 없이 c2 에 저장되어있는 값을 1 증가시킴
c2++;  // c2++ 대신 c2 = c2+1 을 사용하면 에러가 발생함. c2+1 의 연산결과는 int형이기 때문





// ex.2
char mk = 'a';


//char mk2 = mk + 1;  // 에러 발생함. mk + 1 은 연산결과가 int형임

// 상수 또는 리터럴 간의 연산은 컴파일러가 미리 계산하기 때문에 형변환을 안해줘도 됨
char mk2 = 'a'+ 1;  // 에러 발생안함. 'a'  + 1 은 릴터럴간의 연산이기 때문에 char 형임

 

 

 

 

산술 변환 

  • 연산 전에 피연산자의 타입을 일치시키는 것
  • 두 피연산자의 타입을 같게 일치시킴 (보다 큰 타입으로 일치)
    • // long 타입 + int 타입  → long 타입으로 변환해야함
      long + int → long + long → lon → long
      
      // float 타입 + int 타입 → float 타입으로 변환
      float + int → float + float → float
      
      // double 타입 + float 타입 → double 타입으로 변환
      double + float → double + double → double
  • 피연산자의 타입이 int 보다 작은 타입(byte, short, char)이면 int로 변환함
    • int 타입으로 처리했을 때 가장 효율적으로 처리할 수 있기 때문임
    • //byte 타입 + short 타입 → int 타입으로 변환
      byte + short → int + int → int
      
      //char 타입 + short 타입 → int 타입으로 변환
      char + short → int + int → int

 

 

 

 

 

■ 문자 → 숫자

□ String to Int

  • Integer.parseInt(String값)
  • Integer.valueOf(String값)
class prac{
    public static void main(String[] args){
        System.out.println(Integer.parseInt("10"));  // 10
        
        System.out.println(Integer.valueOf("22"));  // 22
    }
}

참고) https://terry9611.tistory.com/64

 

Integer.PaseInt, Integer.valoueOf 차이

자바의 데이터타입은 크게 2가지로 나눌 수 있음 primitive byte, short, int, long 과 같이 size가 정해져 있는 값 기본 자료형 object Byte, Short, Integer, Long, Class 과 같이 주소값을 참조하는 형태 객체..

terry9611.tistory.com

 

 

 

 

□ String to Double, Float

  • Double.valueOf(String값)
  • Float.valueOf(String값)
class prac{
    public static void main(String[] args){
        System.out.println(Double.valueOf("10"));  // 10.0
        
        System.out.println(Float.valueOf("5"));  // 5.0
    }
}

 

 

□ String to Long, Short

  • Long.parseLong(String값)
  • Short.parseShort(String값)
class prac{
    public static void main(String[] args){
        System.out.println(Long.parseLong("10"));  // 10
        
        System.out.println(Short.parseShort("22"));  // 22
    }
}

 

 

 

 

■ 숫자 → 문자

□ Int to String

  • String.valueOf(Int값)
  • Integer.toString(Int값)
  • 덧셈연산자 (문자열 + 숫자)
class prac{
    public static void main(String[] args){
        System.out.println(String.valueOf(10));  // 10
        
        System.out.println(Integer.toString(22));  // 22
        
        System.out.println("" + 15);  // 15
    }
}

 

 

 

□ Double, Float to String

  • Float to String
    • String.valueOf(Float값)
    • Float.toString(Float값)
  • Double to String
    • String.valueOf(Double값)
    • Double.toString(Double값)

 

 

class prac{
    public static void main(String[] args){
    	float f_num = 10.10f;
    	double d_num = 11.12;
    	
        // Float → 문자
        System.out.println(String.valueOf(f_num));  // 10.1
        System.out.println(Float.toString(f_num));  // 10.1
        
        // Double → 문자
        System.out.println(String.valueOf(d_num));  // 11.12
        System.out.println(Double.toString(d_num));  // 11.12
        
    }
}

 

 

■ 정수 ↔ 실수

□ Double, Float to Int

  • (int)실수값
class prac{
    public static void main(String[] args){
    	double d_num = 10.101010;
    	float f_num = 15.151515f;
    	
    	System.out.println((int)d_num);  // 10
        
    	System.out.println((int)f_num);  // 15
        
    }
}

 

 

 

□ Int to Double, Float

  • (float)정수값
  • (double)정수값
class prac{
    public static void main(String[] args){
        int i_num = 10;
    	
    	System.out.println((float)i_num);  // 10.0
        
    	System.out.println((double)i_num);  // 10.0
        
    }
}

 

 

 

 

 

 

반올림 - Math.round()

  • 실수를 소수점 첫 째 자리에서 반올림한 정수를 반환
// ex.1
long result = Math.round(4.52);  // 5


// ex.2
double pi = 3.1451592;
double shortPi = Math.round(pi*1000) / 1000.0;   //  3142/ 1000.0
System.out.println(shortPi);    // 3.142


//ex.3  값 3.14을 얻으려면?
double piTwo = 3.141592;
System.out.println((int)(piTwo*1000)/1000.0); // 3.141

 

 

 

나머지 연산자 -  %

  • 나누는 피연산자는 0이 아닌 정수만 허용
  • 나누는 피연산자의 부호는 무시함
    System.out.println(10%8);    // 2
    System.out.println(10%-8);   // 2
    System.out.println(-10%8);   // -2​

 

 

 

 

비교 연산자

// ex.1
System.out.println(10==10.0f);  // true


float flo = 0.1f;  // f 에 0.100000000149011612 로 저장됨
double dou = 0.1;  // d 에 0.100000000000000001 로 저장됨
double dou2 - (double)f;

// 실수형은 근사값으로 저장되기 때문에 오차가 발생할 수 있음.
System.out.println(0.1 == 0.1f);  // false   → 0.1f 는 저장할 때 2진수로 변환하는 과정에서 오차가 발생함
System.out.println(0.1 == flo);  // flase    → 0.1f 는 저장할 때 2진수로 변환하는 과정에서 오차가 발생함
System.out.println(0.1 == 0.1d);  // true
System.out.println(0.1 == dou);  // true

System.out.println(dou == flo);  // false
System.out.println(dou2 == dou);  // false
System.out.println(dou2 == flo);  // true

// double 타입과 float 타입을 비교하려면 double 타입을 float 타입으로 형변환 시켜줘야함
System.out.println((float)dou == flo);  // true

 

 

 

 

문자열 비교

  • 문자열 비교에는 '==' 대신 'equals()' 를 사용해야한다.
  • '==' 는 객체가 다르면 내용이 같더라도 객체가 다르면 false로 출력함
  • 'equals()' 는 객체가 달라도 내용만 같으면 true로 출력함
  • 만약에 대소문자를 구별하지 않고 비교하고 싶으면, 'equalsIgnoreCase()' 를 사용하면 됨
// ex.1
String str1 ="abc";
String str2 ="abc";
System.out.println(str1==str2);  // true
System.out.println(str1.equals(str2));  // true


// ex.2
String str3 = new String("abc");  // String 클래스의 객체 생성
String str4 = new String("abc");  // String 클래스의 객체 생성
System.out.println( str3==str4);  // false. 이래서 '==' 대신 'equal()' 을 써야함
System.out.println( str3.equals(str4));  // true


// ex.3
String str5 = new String("abc");
String str6 = new String("Abc");

System.out.println(str5.equals(str6));  // false
System.out.println(str5.equalsIgnoreCase(str6));  // true
System.out.println(str5.equalsIgnoreCase("aBc"));  // true

 

 

논리연산자

  • ||  → or
    • 피 연산자 중 어느 한 쪽만 true 이면 true 임 
  • &&  → and
    • 피연사 양쪽 모두 true 이어야 true임 
    • && 가 || 보다 연산 우선 순위가 높음

 

 

// ex.1   i는 2의 배수 또는 3의 배수이다
i%2==0 || i%3 ==0;

// ex.2   x 는 10보다 크고 20보다 작다 
10 < x && x < 20;

// ex.3   i는 2의 배수 또는 3의 배수지만 6의 배수는 아니다
(i%2==0 || i%3==0) && (i%6 != 0);

// ex.4   문자 ch는 숫자 ('0' ~ '9')이다
'0' <= ch && ch <= '9';

// ex.5   문자 ch는 대문자 또는 소문자이다.
('a' <= ch && ch <= 'z') || ('A' <= ch <= 'Z');

 

 

 

조건 연산자(삼항 연산자)    ?  :

  • 조건식, 식1, 식2 모두 세 개의 피연산자를 필요로 하는 삼항 연산자임
  • 조건식의 결과에 따라 연산결과를 달리함
  • if 문 대신 조건 연산자를 사용하면 코드를 더 간결하게 쓸 수 있음
  • 조건 연산자를 중첩하면 셋 이상 중의 하나를 결과로 얻을 수 있음
  • 조건 연산자의 식1, 식2가 서로 타입이 다른 경우 산술 변환이 일어남

 ㅡ

 

// 조건 연산자 중첩
// x값이 양수면 1, 0이면 0, 음수면 -1
result = x > 10 ? 1 : (x==0 ? 0: -1);

 

조건 연산자 예제

  • 조건 연산자를 이용해서 변수의 절대값을 구한 후, 부호를 붙여 출력하는 예제
public static void main(String[] args) {
  int x = 10, y= -5, z=0;
  int absX, absY, absZ;
  char signX, signY, signZ;

  absX = x>=0 ? x: -x; // x의 값이 음수면, 양수로 만듦
  absY = y>=0 ? y: -y;
  absZ = z>-0 ? z: -z;

  signX = x>0 ? '+' : (x==0 ? ' ' : '-');
  signY = y>0 ? '+' : (y==0 ? ' ' : '-');
  signZ = z>0 ? '+' : (z==0 ? ' ' : '-');

  System.out.printf("x = %c%d%n", signX, absX);  // x = +10
  System.out.printf("y = %c%d%n", signY, absY);  // y = -5
  System.out.printf("z = %c%d%n", signZ, absZ);  // z =  0
}

 

 

 

대입 연산자

  • 오른쪽 피연산자를 왼쪽 피연산자에 저장 후 저장된 값을 반환
  • 연산자들 중에서 가장 낮은 우선순위를 가지고 있음. 제일 나중에 수행됨
  • 진행 방향이 오른쪽에서 왼쪽임
  • 대입 연산자의 왼쪽 피연산자를 lvalue(left value), 오른쪽 피연산자를 rvalue(right value) 라고 함
  • rvalue에는 식이나 상수 등 모든 타입이 가능
  • lvalue에는 변수처럼 값을 변경할 수 있는 것이어야함. 리터럴이나 상수는  안됨

 

 

복합 대입 연산자 종류

 

 

 

비트 연산자

  • 피연산자를 비트단위로 논리 연산하는 것
  • 피연산자를 이진수로 표현했을 때의 각 자리의 규칙을 따름
  • 피연산자로 실수는 안됨. 정수만 가능
  • 비트연산에서도 피연산자의 타입을 일치시키는 산술 변환이 일어날 수 있음
  • 비트 or 연산자 '|' 는 주로 특정 비트의 값을 변경할 때 사용함
  • 비트 and 연산자 '&' 는 주로 특정 비트의 값을 뽑아낼 때 사용함 
  • 비트 XOR 연산자 '^' 는 원래의 값으로 돌아오는 특징이 있어서 간단한 암호화에 사용됨
  • ~ 비트 전환 연산자
    • 피연산자의 1의 보수를 얻을 수 있음
    • ex) ~13 → ~1101 → 0010 
    • 양의 정수 p가 있을 때, p 에 대한 음의 정수를 얻으려면 '~p+1' 을 계산하면 됨
    • 음의 정수 n이 있을 때, n에 대한 양의 정수를 얻으려면 '~(n-1)' 을 계산하면 됨
    • '~~p' 는 변수 p의 원래 값이지만 연산결과의 타입이 byte가 아니라 int 타입임
비트 논리 연산자
& 비트 교집합 연산자
AND 연산자
피연산자 모두 '1'이어야만 '1'을 결과로 얻음.
그 외는 '0'을 얻음
value1 & value2
| 비트 합집합 연산자
OR 연산자
피연산자 중 한 쪽 값이 '1'이면 '1'을 얻음
그 외는 '0'을 얻음
value1 | value2
^ 비트 차집합 연산자
XOR 연산자
피연산자의 값이 서로 다를 때만 '1'을 결과로 얻음
같을 때는 '0'을 얻음
value1 ^ value2
~ 비트 부정 연산자
비트 전환 연산자
'1'일 경우 '0'을 얻음. '0'일 경우 '1'을 얻음 ~ value1

 

비트 연산자의 연산 결과

x y x | y x & y x ^ y
1 1 1 1 0
1 0 1 0 1
0 1 1 0 1
0 0 0 0 0

 

 

 

AND 계산

 

 

 

OR 계산

 

 

XOR 계산

 

 

 

 

 

비트 연산 예제

// ex.1   or 연산  
// 0xAB | 0xF  = 0xAF
// 피연산자 0xAB의 마지막 4 비트를 'F' 로 변경함
// 0xAB = 10101011 (2진수)
// 0xF = 00001111 (2진수)
// 0xAF = 10101111 (2진수)


// ex.2   and 연산 
// 0xAB & 0xF = 0xB
// 피연산자의 마지막 4비트가 어떤 값인지 알아낼 수 있음
// 0xAB = 10101011 (2진수) 
// 0Xf = 00001111 (2진수)
// 0xB  = 00001011 (2진수)


// ex.3   xor 연산
// 0xAB ^ 0xF = 0xA4, 0xA4 ^ 0xF = 0xAB
// XOR 연산을 수행하면 원래의 값으로 돌아오는 특징이 있어서 간단한 암호화에 사용됨
// 0xAB = 10101011 (2진수)
// 0xF = 00001111 (2진수)
// 0xA4 = 10100100 (2진수)
// 0xF = 00001111 (2진수) 
// 0xAB = 10101011 (2진수)

 

 

 

 

 


문자열 자르기  - substring

substring(int index)

  • 인자값은 int 형으로 해야함
  • 입력받은 인자값을 index로 해당 위치를 포함하여 이후의 모든 문자열을 리턴함 (index 값 포함)

 

String str = "0123456789";  //
System.out.println(str.substring(5));  // 56789

 

substring(int beginIndex, int endIndex)

  • 인자값이 두 개임
  • 첫 번째 입력 받는 beginIndex 값은 가져올 문자열의 시작 부분을 지정함 (beginIndex 값 포함)
  • 두 번째 입력 받는 endIndex 값은 가져올 문자열의 끝을 지정하는 값임  (endIndex 값 포함 안함)
String str = "0123456789";
System.out.println(str.substring(2,5));  // 234

 


비트 연산 예제2

public static void main(String[] args) {
  int x = 0xAB, y = 0xF;

  System.out.printf("x=%#X \t\t%s%n",x, toBinaryString(x));
  System.out.printf("y= %#X \t\t%s%n", y, toBinaryString(y));
  System.out.printf("%#X | %#X = %#X \t%s%n", x, y, x|y, toBinaryString(x|y));
  System.out.printf("%#X & %#X = %#X \t%s%n", x, y, x&y, toBinaryString(x&y));
  System.out.printf("%#X ^ %#X = %#X \t%s%n", x, y, x^y, toBinaryString(x^y));
  System.out.printf("%#X ^ %#X = %#X \t%s%n", x, y, x^y^y, toBinaryString(x^y^y));

} // end of main

static String toBinaryString(int x) {  // 10진 정수를 2진수로 변환하는 메서드
  String zero = "00000000000000000000000000000000";  // 32개
  String tmp = zero + Integer.toBinaryString(x);
  return tmp.substring(tmp.length()-32);  // 4byte(32bit) 자리수 표현

}




/* 출력값

x=0XAB 		00000000000000000000000010101011
y= 0XF 		00000000000000000000000000001111
0XAB | 0XF = 0XAF 	00000000000000000000000010101111
0XAB & 0XF = 0XB 	00000000000000000000000000001011
0XAB ^ 0XF = 0XA4 	00000000000000000000000010100100
0XAB ^ 0XF = 0XAB 	00000000000000000000000010101011

*/

 

 

 

 

~ 비트 전환 연산자 예제

public static void main(String[] args) {
  byte p = 10;
  byte n = -10;
  
  System.out.printf(" p   =%d \t%s%n",    p,    toBinaryString(p));
  System.out.printf("~p   =%d \t%s%n",    ~p,   toBinaryString(~p));
  System.out.printf("~p+1 =%d \t%s%n",  ~p+1, toBinaryString(~p+1));
  System.out.printf("~~p  =%d \t%s%n",    ~~p, toBinaryString(p));
  System.out.println();
  System.out.printf("n = %d%n", n);
  System.out.printf("~(n-1) = %d%n", ~(n-1));

}


static String toBinaryString(int x) {
  String zero = "00000000000000000000000000000000";
  String tmp = zero + Integer.toBinaryString(x);
  return tmp.substring(tmp.length()-32);

}



/* 출력값

 p   =10 	00000000000000000000000000001010
~p   =-11 	11111111111111111111111111110101
~p+1 =-10 	11111111111111111111111111110110
~~p  =10 	00000000000000000000000000001010

n = -10
~(n-1) = 10

*/

 

 

 

 

 

 

 

 

 

쉬프트 연산자

  • 변수 << 이동할 비트수
    • 오른쪽으로 이동할 떄 뒷자리의 비트가 무조건 0으로 옴
  • 변수 >> 이동할 비트수
    • 왼쪽으로 이동할 때 가장 앞자리 수가 1이면(=음수) 1로 채워지고, 0이면(=양수) 0으로 채워짐
  • 곱셈이나 나눗셈으로 같은 결과를 얻을 수 있는데 쉬프트 연산자를 쓰는 이유는 속도 때문임
    쉬프트 연산자가 더 빠름. 단, 가독성은 떨어짐. 그래서 곱셈이나 나눗셈을 주로 사용함
  • 쉬프트 연산자의 좌측 피연산자는 산술변환이 적용되어 int 보다 작은 타입은 int 타입으로 자동 변환됨.
    연산 결과 역시 int 타입임
  • 쉬프트 연산자의 우측 피연산자는 산술변환이 적용되지 않음

 

 

쉬프트 연산자 정리

 

 

 

 

 

 

 

 

 

 

쉬프트 연산자 예제

public static void main(String[] args) {
  int dec = 8;

  System.out.printf("%d >> %d = %4d \t %s%n", dec, 0, dec >> 0, toBinaryString(dec >> 0));
  System.out.printf("%d >> %d = %4d \t %s%n", dec, 1, dec >> 1, toBinaryString(dec >> 1));
  System.out.printf("%d >> %d = %4d \t %s%n", dec, 2, dec >> 2, toBinaryString(dec >> 2));
  System.out.println();

  System.out.printf("%d << %d = %4d \t %s%n", dec, 0, dec << 0, toBinaryString(dec << 0));
  System.out.printf("%d << %d = %4d \t %s%n", dec, 1, dec << 1, toBinaryString(dec << 1));
  System.out.printf("%d << %d = %4d \t %s%n", dec, 2, dec << 2, toBinaryString(dec << 2));
  System.out.println();

  dec = -8;
  System.out.printf("%d >> %d = %4d \t %s%n", dec, 0, dec >> 0, toBinaryString(dec >> 0));
  System.out.printf("%d >> %d = %4d \t %s%n", dec, 1, dec >> 1, toBinaryString(dec >> 1));
  System.out.printf("%d >> %d = %4d \t %s%n", dec, 2, dec >> 2, toBinaryString(dec >> 2));
  System.out.println();

  System.out.printf("%d<< %d = %4d \t %s%n", dec, 0, dec << 0, toBinaryString(dec << 0));
  System.out.printf("%d << %d = %4d \t %s%n", dec, 1, dec << 1, toBinaryString(dec << 1));
  System.out.printf("%d << %d = %4d \t %s%n", dec, 2, dec << 2, toBinaryString(dec << 2));


}


static String toBinaryString(int x) {
  String zero = "00000000000000000000000000000000";
  String tmp = zero + Integer.toBinaryString(x);
  return tmp.substring(tmp.length()-32);

}
	
    
    
/* 출력값

8 >> 0 =    8 	 00000000000000000000000000001000
8 >> 1 =    4 	 00000000000000000000000000000100
8 >> 2 =    2 	 00000000000000000000000000000010

8 << 0 =    8 	 00000000000000000000000000001000
8 << 1 =   16 	 00000000000000000000000000010000
8 << 2 =   32 	 00000000000000000000000000100000

-8 >> 0 =   -8 	 11111111111111111111111111111000
-8 >> 1 =   -4 	 11111111111111111111111111111100
-8 >> 2 =   -2 	 11111111111111111111111111111110

-8<< 0 =   -8 	 11111111111111111111111111111000
-8 << 1 =  -16 	 11111111111111111111111111110000
-8 << 2 =  -32 	 11111111111111111111111111100000

*/

 

쉬프트 연산 예제2

public static void main(String[] args) {
  int dec = 8;
  int hex = 0xABCD;
  int mask = 0xF;  // 0x000F

  System.out.printf("hex = %X%n", hex);  // hex = ABCD
  System.out.printf("%X%n", hex & mask);  // D

  hex = hex >> 4;  // hex / 2^4
  System.out.printf("%X%n", hex & mask);  // C

  hex = hex >> 4; 
  System.out.printf("%X%n", hex % mask);  // B

  hex = hex >> 4;  
  System.out.printf("%X%n", hex & mask);  // A

}

 

 

 

 

 

728x90