연산자(Operator)


연산자 종류와 연사순서, 연산 순서를나타낸 표이다.

아래 순서는 연산자 단일경우이다. 연산자가 같이 있으면 경우에 따라 달라진다.

 



그럼 연산자의 종류부터 차근히 알아보자.


1. 종류


1) 산술연산자


- 이항연산자 : *,  /,  %,  +,  -

- 단항(증감)연산자 : ++,  --


단항(증감)연산자를 써보자.


<예제 1>


class Op1{

    public static void main(String[] args){

        int a = 10;

        a++; //후위연산자 a = a+1;

        ++a; //전위연산자

        System.out.println("a=" + a);

    }

}


※ 결과값

a=12


아래 두개의 예제를 비교하여 살펴보자.

<예제2>

class Op1 {


public static void main(String[] args) {

// TODO 연산자1

int a = 10, b;

b = ++a;

//b=a++;

System.out.println("a="+a);

System.out.println("b="+b);

}


}


※ 결과값

a=11

b=11


<예제 3>


class Op1{

    public static void main(String[] args){        

        int a = 10, b;

        //b = ++a;

        b = a++;

        System.out.println("a=" + a);

        System.out.println("b=" + b);

        

    }

}


※ 결과값

a=11

b=10


어떻게 이런 다른 결과가 나오는 것일까?


왜냐하면 연산자우선순위 때문에 a값이 증감되기 전에 b로 넘어가버렸기 때문이다.

이렇게 증감연산자을 계산식과 연동할 경우 오류를 찾기 어렵기 때문에

증감연산자는 될 수 있으면 계산식과 연동하지 말고 단독으로 쓰는 것이 좋다.


2) 비교연산자


>, <, >=, <=, ==(같다), !=(같지 않다)



3) 논리연산자 (단락회로 기능)


&&(and), ||(or), !(not)


t = true

f = fause


 a

b

a && b 

a || b 

!a 

a^b 

 t

 f 

 t

f

f

t

 f

t

t

 f

 f 



여기서 ! 는 스위치처럼 한 번씩 왔다갔다 반복을 하기 때문에 Toggle이라고 한다. (ex_바둑게임)



4) 대입(치환)연산자


대입연산자

 = (오른쪽에 있는 값은 왼쪽에 집어넣어라)

복합대입연산자

 +=, -=, *=, /=, .... 

(+= 는 '변수 = 변수 + 값'을 생략한 것이다.)

(다른 연산자와 조합해서 사용한다. 이는 누적 연산자라고 한다.)


class Op2{

    public static void main(String[] args){

        int a = 10;

        a = 5;

        a = 2;

        a = 3;

        System.out.println("a=" + a)

    }

}    


※ 결과값

3


변수는 아무리 다른 값을 집어넣어도 하나밖에 저장이 안되기 때문에 마지막에 집어 넣은 값이 출력값이 된다.

이렇듯 대입연산자는 값이 누적되지 않고 계속 덮어 씌어진다.


class Op2{

    public static void main(String[] args){

        /*

        int a = 10;

        a = 5;

        a = 2;

        a = 3;

        System.out.println("a=" + a)

        */

        

        int a = 10;

        a += 5; // a = a+5; 

        a += 2; // a = a+2;

        a += 3; // a = a+3;

        System.out.println("a=" +a);

    }

}    



※ 결과값

20


이 때 a의 값은 20이 된다. 누적되어서 계산 되었기 때문이다. 

대입연산자와 달리 복합대입연산자는 다른 연산자를 포함하고 있지만
생략하여 나타낸 연산자기 때문에 값이 누적되어 계산된다.


이렇듯 연산자에게 가장 중요한 것은 '우선순위'이다.

연산우선순서를 모두 외울 수 있지만 쉽지 않다.

연산자는 괄호()를 묶어 연산하는 습관을 기른다. 

정확하고 안전한 것이 가장 중요하다.


5) 비트연산자


& (and연산자), | (or연산자), ^ (exclusive-or, xor, 베타적인or, 데이터를 암호화 하거나 복구한다.), >>, >>> << ~, ...


프로그램의 성능을 올리기 위해 사용하는 연산자이다.

최근 하드웨어의 사향의 상향 평준화 되었기 때문에 

하드웨어를 다루지 않는이상 잘 쓰지는 않는다.


class Op3 {

    public static void main(){

        int a = 10, b = 5;

        

        System.out.println("a&&b" + a&&b);

    }        

}

// 논리 연산식은 참과 거짓으로만 판단할 수 있기 때문에 오류가 된다.


※ 결과값

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 

The operator && is undefined for the argument type(s) String, int


at operator.Op3.main(Op3.java:8)



class Op3 {

    public static void main(String[] args){

        int a = 10, b = 5;

        

        //System.out.println("a&&b" + a&&b);

        System.out.println("a>5&&b<3" + (a>5&&b<3));

    }        

}



※ 결과값

 a>5&&b<3false


변수의 값이 참인지 거짓인지를 물었기 때문에 값이 위와 같이 나온다.


비트연산자 & 는 논리연산자 &&와는 다르게 

숫자를 대변해도 값이 나온다. 비트연산자는 이진수를 계산하기 때문이다.


class Op3 {

    public static void main(String[] args){

        int a = 10, b = 7;

        

        //System.out.println("a&&b" + a&&b);

        System.out.println("a>5&&b<3" + (a>5&&b<3));

        

        System.out.println("a>5&b<3" + (a>5&b<3));

        System.out.println("a&b" + (a&b));

    }        

}

※ 결과값

a>5&&b<3false

a>5&b<3false

a&b2

 


논리연산자는 단락회로기능을 가지고 있다. '단락회로기능'이란 

이미 앞에서 계산된 것은 계산하지 않는 것을 말한다.


아래의 예제들을 비교하면서 생각해보자.


class Op3 {

    public static void main(String[] args){

        int a = 10, b = 7;

        

        //System.out.println("a&&b" + a&&b);

        System.out.println("a>5&&b<3" + (a>5&&b<3));

        

        System.out.println("a>5&b<3" + (a>5&b<3));

        System.out.println("a&b" + (a&b));

        

        System.out.println(a>12 && ++b>5);

        System.out.println(a + ", " + b);

    }        

}


※ 결과값

a>5&&b<3false

a>5&b<3false

a&b2

false

10, 7





class Op3 {

    public static void main(String[] args){

        int a = 10, b = 7;

        

        //System.out.println("a&&b" + a&&b);

        System.out.println("a>5&&b<3" + (a>5&&b<3));

        

        System.out.println("a>5&b<3" + (a>5&b<3));

        System.out.println("a&b" + (a&b));

        

        System.out.println(a<12 && ++b>5);

        System.out.println(a + ", " + b);

    }        

}


※ 결과값

a>5&&b<3false

a>5&b<3false

a&b2

true

10, 8


이 값의 변화는 논리연산자(&&, ||)가 가진 단락회로기능 때문이다.



^(exclusive-or, xor, 베타적인or, 데이터를 암호화 하거나 복구한다.

^는 서로의 값이 다르면 참 서로의 값이 같으면 거짓이다.

키값만 있다면 데이터를 암호화 할 수도, 복구 할 수도 있다.


<암호화>

   11010110

^ 11000011 (key)

-------------------------

    00010101


<복구>

   00010101 (key)

^ 11000011

----------------

    11010110




class Op4{

    public static void main(String[] args){

        int data = 34876;

        int key = 2986;

        

        int enc = data^key;

        System.out.println("암호화된 값 : " + enc);

        

        int dec = enc ^ key;

        System.out.println("복호화된 값 : " + dec);

    }

}


※ 결과값

암호화된 값 : 33686

복호화된 값 : 34876


비트연산자는 2진수로 연산함을 잊지말자!



6) 캐스팅 연산자 (강제형변환 연산자)


- 묵시적(암시적) : 작은 그릇을 큰 그릇에 넣었기 때문에 자동으로 캐스팅 된다.

- 명시적 : (data type) 변수


이 변수의 형식을 괄호 안에 있는 형식으로 강제로 바꾸겠다는 말이다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 오류가 난다.

        int i1 = d1 + d2;

    }

}


이를 캐스팅연산자를 사용하여 강제 형변환 해주면,


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

    }

}


※ 결과값

i1 = 5


위와 같은 결과가 나오는 이유는 강제형변환을 했기 때문에. 0.8을 손해보아서 이다. 

입력되는 숫자를 예측하기 어려운 경우에 많이 쓰인다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1;

        System.out.println("d1 =" +d1);

    }

}


※ 결과값

i1 = 5

d1 =5.0



이 경우 i1 값은 명시적 캐스팅을 헀고, d1의 경우

 작은그릇을 큰그릇에 넣을 수 있기 때문에 암시적 캐스팅이 되었다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        b1 = b1 + 5;

        System.out.println("b1 =" + b1);

    }

}


※ 결과값

오류가 난다



이렇게 하면 오류가 난다. 

문법적으로는 문제가 없으나 이는 하드웨어적인 이해가 필요하다. 

작은 연산결과를 임시로 저장하는 곳을 레시스터라고 하는데 

그 때 임시로 저장되는 형식이 기본형인 int이다. 

int로 임시저장된 값을 bite로 다시 바꾸려고 하기 때문에 오류가 난다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        //임시연산저장소에서 int로 저장된 값을 형변환 해준다.

        b1 = (byte)(b1 + 5);

        System.out.println("b1 =" + b1);

    }

}


※ 결과값


i1 = 5

d1 =5.0

b1 = 5

b1 =105

b1 =110



강제형변환을 하지 않는 방법은 복합치환연산자를 쓰는 것이다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        //b1 = (byte)(b1 + 5);

        b1 += 5; // b1 = b1 + 5;

        System.out.println("b1 =" + b1);

    }

}



※ 결과값

i1 = 5

d1 =5.0

b1 = 5

b1 =105

b1 =110


이렇듯 복합치환연산자는 자동캐스팅기능이 포함이 되어있어 연산이 가능하다.


하드웨어 문제로 연산이 안되는 또다른 문제가 있다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        //b1 = (byte)(b1 + 5);

        b1 += 5; // b1 = b1 + 5;

        System.out.println("b1 =" + b1);

        

        float f1 = 3.14;

        System.out.println("f1 =" + f1);

        

    }

}


※ 결과값

오류


컴퓨터는 2진수이기 때문에 정수처리를 한다. 실수처리를 잘 못한다. 

컴퓨터가 실수를 처리할 때는 정수부와 실수부를 따로 저장한다. 

정수부와 실수부를 따로 저장할 때 타입은 실수의 기본형인 double이다. 

이런 경우 역시 캐스팅으로 해결한다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        //b1 = (byte)(b1 + 5);

        b1 += 5; // b1 = b1 + 5;

        System.out.println("b1 =" + b1);

        

        float f1 = (float)3.14;

        System.out.println("f1 =" + f1);

        

    }

}



※ 결과값


i1 = 5

d1 =5.0

b1 = 5

b1 =105

b1 =110

f1 =3.14



다른 방식으로 깔끔하게 표현을 바꾸어 보자.

강제형변환은 정수형 일 때만 한다. 그런데 실수형의 경우기 때문에 강제형변환 표현이 조금 지저분하다. 다른 방법으로 이를 표현하면 아래와 같이 된다.


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        //b1 = (byte)(b1 + 5);

        b1 += 5; // b1 = b1 + 5;

        System.out.println("b1 =" + b1);

        

        //소문자나 대문자 f를 형변환 해야하는 값 옆에 써준다.

        float f1 = 3.14f;

        System.out.println("f1 =" + f1);

        

    }

}




문자의 경우는  어떻게 캐스팅이 될까?


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        //b1 = (byte)(b1 + 5);

        b1 += 5; // b1 = b1 + 5;

        System.out.println("b1 =" + b1);

        

        //float f1 = (float)3.14;

        float f1 = 3.14f;

        System.out.println("f1 =" + f1);

        

        f1 = f1 + 2.5f;

         System.out.println("f1 = " + f1);

        

        //아스키코드기 때문에 숫자로 자동 형변환 해준다.

        int i2 = 'a';

        System.out.println("i2 = " + i2);

        

        //아스키코드기 때문에 문자로 자동 형변환 해준다.

        char c1 = 98;

        System.out.println("c1 = " + c1);

    }

}


※ 결과값

i1 = 5

d1 =5.0

b1 = 5

b1 =105

b1 =110

f1 =3.14

f1 = 5.6400003

i2 = 97

c1 = b



매우 큰 값의 경우는 어떨까?


class Op5{

    public static void main(String[] args){

        double d1 = 3.5, d2 = 2.3;

        

        //값을 담고 있는 그릇의 크기가 int이기 때문에 안된다.

        int i1 = (int)d1 + (int)d2;

        System.out.println("i1 = " + i1);

        

        d1 = (double)i1; //d1 = (double) i1;

        System.out.println("d1 =" +d1);

        

        byte b1 = (byte)i1;

        System.out.println("b1 = " + b1);

        

        b1 = 100 + 5;

        System.out.println("b1 =" + b1);

        

        //b1 = (byte)(b1 + 5);

        b1 += 5; // b1 = b1 + 5;

        System.out.println("b1 =" + b1);

        

        //float f1 = (float)3.14;

        float f1 = 3.14f;

        System.out.println("f1 =" + f1);

        

        f1 = f1 + 2.5f;

         System.out.println("f1 = " + f1);

        

        //아스키코드기 때문에 숫자로 자동 형변환 해준다.

        int i2 = 'a';

        System.out.println("i2 = " + i2);

        

        //아스키코드기 때문에 문자로 자동 형변환 해준다.

        char c1 = 98;

        System.out.println("c1 = " + c1);

        

        //i2 = 10000000000;

        

        //정수형으로 안되는 값이기 때문에 L이라는 꼬리표로 형변환시켜준다.

        long var = 10000000000L;

        

    }

}


7) 삼항연산자 (조건연산자)

<문법>
조건식 ? 참일 때 처리할 내용 : 거짓일 때 처리할 내용


class Op7{
    public static void main (String[] args) {
        int data = 8;
        
        // data란 변수가 5보다 크면 1에 저장하고 아니면 0에 저장한다.
        //
        int result = data > 5 ? 1 : 0;
        boolean result2 = data > 6 ? true : false;
        System.out.println("결과 : " + result + "\t" + result2);
        
    }

}



★ 연습문제 ★

https://gist.github.com/muyongseja/472f3c3a8f32a412d4cec00412e935ef


1. 리터를 갤런으로 바꿔보자.

두 개의 double변수를 이용해서 각각 갤런과 리터값을 저장하고

갤런값을 해당하는 리터값으로 바꿔보자.(1갤런은 3.7584리터이다.)


2. 달의 중력은 지구 중력의 17%정도이다.

달에서의 당신의 체중을 계산하는 프로그램을 작성하시오.


66퍼센트 감소하면?

답) 526.32


3. 번개가 얼마나 먼 곳에서 발생했나?

(번개 소리를 들은 사람이 번개가 치는 곳에서부터 몇 피트 정도 떨어져 있는가를 계산하라.

소리는 공기 중은 약 1,100피트/초의 속도로 진행한다.

- 번개를 본 시각과 천둥소리를 들은 시각 사이의 시간을 알면 거리를 계산할 수 있다.

여기서는 7.2초로 가정하자.)











+ Recent posts