본문 바로가기
Language/JAVA

[JAVA] 연산자와 연산식 1 // 단항연산자 이항연산자

by 아이엠제니 2021. 9. 12.

 


 

 

연산자와 연산식

  • 프로그램에서 데이터를 처리하여 결과를 산출하는 것은 연산(operations)라고 함
  • 연산에 사용되는 표시나 기호를 연산자(operator)라고 함
  • 연산되는 데이터는 피연산자(operand)라고 함
  • 연산자와 피연산자를 이용하여 연산의 과정을 기술하는 것은 연산식(expressions)라고 함
  • +, -, *, == 은 연산자
  • x, y, z 변수는 피연산자 
  • 연산자는 필요로 하는 피연산자의 수에 따라 단항, 이항, 삼항 연산자로 구분
단항 연산자: ++x;
이항 연산자: x + y;
삼항 연산자: (sum>90) ? "A" : "B";

 

 


연산의 방향과 우선순위

  1. ( )
  2. * / %
  3. + -
  • 우선순위가 같은 연산자의 순서 - p.67 참고
100 * 2 / 3 % 5
* / % 같은 우선순위를 갖고 있음
방향이 왼쪽에서 오른쪽으로 수행

> 대부분은 왼쪽에서 오른쪽으로 연산 시작

 

a = b = c = 5;

> 단항 연산자(++, --, ~, !), 부호 연산자(+, -), 대입 연산자(=, +=, -+, ...)은 오른쪽에서 왼쪽으로 연산

 

* 우선순위

1. 단항, 이항, 삼항 순
2. 산술, 비교, 논리, 대입 연산자 순
3. 단항과 대입 연사자를 제외한 모든 연산의 방향은 왼->오
4. 복잡한 연산식에는 괄호()를 사용해서 우선순위 정함

 

 


단항 연산자

  • 피연산자가 단 하나뿐인 연산자를 말함
  • 부호 연산자(+, -), 증감 연산자(++, --), 논리 부정 연산자(!), 비트 반전 연산자(~)

 

 


부호 연산자(+, -)

  • 부호 연산자의 산출 타입은 int 타입이 된다
package thisisjava.chap03.num01;

public class SignOperatorExample {
    public static void main(String[] args) {
        int x = -100;
        int result1 = +x;
        int result2 = -x;
        System.out.println("result1=" + result1);
        System.out.println("result2=" + result2);

        short s = 100;
//        short result3 = -s; //컴파일 에러
        int result3 = -s;
        System.out.println("result3=" + result3);
    }
}

> short ㄴㄴ int ㅇㅋ

 

 


증감 연산자 (++, --)

  • ++ 1 증가, -- 1 감소
  • ++ 피연산자: 다른 연산을 수행하기 에 피연산자의 값을 1 증가시킴
  • -- 피연산자: 다른 연산을 수행하기 에 피연산자의 값을 1 감소시킴
  • 피연산자 ++: 다른 연산을 수행한 에 피연산자의 값을 1 증가시킴
  • 피연산자 --: 다른 연산을 수행한 에 피연산자의 값을 1 감소시킴
package thisisjava.chap03.num01;

public class IncreaseDecreaseOperatorExample {
    public static void main(String[] args) {
        int x = 10;
        int y = 10;
        int z;

        System.out.println("----------");
        x++; //11
        ++x; //12
        System.out.println("x=" + x); //12

        System.out.println("----------");
        y--; //9
        --y; //8
        System.out.println("y=" + y); //8

        System.out.println("----------");
        z = x++; //12 //13
        System.out.println("z=" + z); //12
        System.out.println("x=" + x); //13

        System.out.println("----------");
        z = ++x; //14
        System.out.println("z=" + z); //14
        System.out.println("x=" + x); //14

        System.out.println("----------");
        z = ++x + y++; // 15+8
        System.out.println("z=" + z); //23
        System.out.println("x=" + x); //15
        System.out.println("y=" + y); //9
    }
}

 

 


논리 부정 연산자(!)

  • true를 flase로, false를 true로 변경
  • boolean 타입에만 사용할 수 있음
! 피연산자
피연산자가 true이면 false 값 산출
피연산자가 false이면 true 값 산출

 

package thisisjava.chap03.num01;

public class DenyLogicOperatorExample {
    public static void main(String[] args) {
        boolean play = true;
        System.out.println(play);

        play = !play;
        System.out.println(play);

        play = !play;
        System.out.println(play);
    }
}

 

 

 


비트 반전 연산자(~)

  • 정수타입의 피연산자에만 사용
  • 피연산자를 2진수로 표현했을 때 비트값인 0을 1로, 1은 0으로 반전
  • 부호가 반대인 새로운 값이 산출
  • 산출 타입은 int 타입

 

package thisisjava.chap03.num01;

public class BitReverseOperatorExample {
    public static void main(String[] args) {
        int v1 = 10;
        int v2 = ~v1;
        int v3 = ~v1 + 1;
        System.out.println(toBinaryString(v1) + "(십진수: " + v1 + ")");
        System.out.println(toBinaryString(v2) + "(십진수: " + v2 + ")");
        System.out.println(toBinaryString(v3) + "(십진수: " + v3 + ")");
        System.out.println();

        int v4 = -10;
        int v5 = ~v4;
        int v6 = ~v4 + 1;
        System.out.println(toBinaryString(v4) + "(십진수: " + v4 + ")");
        System.out.println(toBinaryString(v5) + "(십진수: " + v5 + ")");
        System.out.println(toBinaryString(v6) + "(십진수: " + v6 + ")");
    }

    public static String toBinaryString(int value) {
        String str = Integer.toBinaryString(value);
        while (str.length() < 32) {
            str = "0" + str;
        }
        return str;
    }
}

 

 



이항 연산자

  • 피연산자가 두 개인 연산자를 말함
  • 산술 연산자, 문자열 연결 연산자, 대입 연산자, 비교 연산자, 논리 연산자, 비트 논리 연산자, 비트 이동 연산자 등

 

 


산술 연산자 (+, -, *, /, %)

  • boolean 타입을 제외한 모든 기본 타입에 사용할 수 있음
int result = num % 3;
0, 1, 2 중의 한 값
num을 3으로 나눈 나머지
  • 피연산자들이 모두 정수 타입이고, int 타입보다 크기가 작은 타입의 경우 모두 int 타입으로 변환 후 연산 수행
    연산의 산출 타입은 int
    byte + byte -> int + int = int
  • 피연산자들이 모두 정수타입이고, long 타입이 있을 경우 모두 long 타입으로 변환 후 연산 수행
    연산의 산출 타입은 long
    int + long -> long + long = long
  • 피연산자 중 실수 타입(float, double)이 있을 경우, 크기가 큰 실수 타입으로 변환 후 연산 수행
    연산의 산출 타입은 실수 타입
    int + double -> double + double = double
  • long을 제외한 정수 타입 연산은 int 타입으로 산출, 피연산자 중 하나라도 실수 타입이면 실수 타입으로 산출

 

package thisisjava.chap03.num01;

public class ArithmeticOperatorExample {
    public static void main(String[] args) {
        int v1 = 5;
        int v2 = 2;

        int result1 = v1 + v2;
        int result2 = v1 - v2;
        int result3 = v1 * v2;
        int result4 = v1 / v2;
        int result5 = v1 % v2;
        double result6 = (double) v1 / v2;

        System.out.println("resutl1=" + result1);
        System.out.println("resutl2=" + result2);
        System.out.println("resutl3=" + result3);
        System.out.println("resutl4=" + result4);
        System.out.println("resutl5=" + result5);
        System.out.println("resutl6=" + result6);
    }
}

> 산술 연산자

 

package thisisjava.chap03.num01;

public class CharOperationExample {
    public static void main(String[] args) {
        char c1 = 'A' + 1;
        char c2 = 'A';
//        char c3 = c2 +1; //컴파일 에러
        char c3 = (char) (c2 + 1); //캐스팅
        System.out.println("c1: " + c1);
        System.out.println("c2: " + c2);
        System.out.println("c3: " + c3);
    }
}

> char 타입이 산술 연산이 될 경우 int 타입으로 변환, 산출 타입은 int 타입

 

 

오버플로우

  • 산출 타입으로 표현할 수 없는 값이 산출되었을 경우, 오버플로우가 발생
    쓰레기값(엉뚱한 값)을 얻을 수 있음
package thisisjava.chap03.num01;

public class OverflowExample {
    public static void main(String[] args) {
        int x = 1000000;
        int y = 1000000;
        int z = x * y;
        System.out.println(z);
    }
}

> int 타입에 저장될 수 있는 값의 범위를 초과

> 그래서 쓰레기값을 얻게 됨

> 변수 x와 y 중 최소 하나라도 long 타입이 되어야 하고, 변수 z가 long 타입이어야 함

package thisisjava.chap03.num01;

public class OverflowExample1 {
    public static void main(String[] args) {
        long x = 1000000;
        long y = 1000000;
        long z = x + y;
        System.out.println(z);
    }
}

> 오버플로우 해결

 

 

정확한 계산은 정수 사용

package thisisjava.chap03.num01;

public class CheckOverflowExample {
    public static void main(String[] args) {
        try {
            int result = safeAdd(2000000000, 2000000000);
            System.out.println(result);
        } catch (ArithmeticException e) {
            System.out.println("오버플로우가 발생하여 정확하게 계산할 수 없음");
        }
    }

    public 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;
    }
}

 

package thisisjava.chap03.num01;

public class AccuracyExample1 {
    public static void main(String[] args) {
        int apple = 1;
        double pieceUnit = 0.1;
        int number = 7;

        double result = apple - number * pieceUnit;

        System.out.println("사과 한개에서 ");
        System.out.println("0.7 조각을 빼면, ");
        System.out.println(result + "조각이 남는다");
    }
}

> 정확하게 계산할 때에는 부동소수점 타입을 사용하지 않는다

 

package thisisjava.chap03.num01;

public class AccuracyExample2 {
    public static void main(String[] args) {
        int apple = 1;

        int totalPieces = apple * 10;
        int number = 7;
        int temp = totalPieces - number;

        double result = temp / 10.0;

        System.out.println("사과 한개에서 ");
        System.out.println("0.7 조각을 빼면, ");
        System.out.println(result + " 조각이 남는다");
    }
}

> 정확하게 계산할 때는 정수 연산 사용

 

NaN과 Infinity 연산

package thisisjava.chap03.num01;

public class InfinityAndNaNCheckExample {
    public static void main(String[] args) {
        int x = 5;
        double y = 0.0;

        double z = x / y;
        double k = x % y;

        System.out.println("z: " + Double.isInfinite(z));
        System.out.println("k: " + Double.isInfinite(k));
        System.out.println("z: " + Double.isNaN(z));
        System.out.println("k: " + Double.isNaN(k));

        System.out.println("z: " + z + 2);// /는 infinity
        System.out.println("y: " + k + 2); // %는 NaN
    }
}

> /는 infinity , %는 NaN

> 연산의 결과가 Infinity 또는 NaN이면 절대로 다음 연산을 수행하지 못하도록 if문을 ㅏ용해서 실행 흐름을 변경함

 

입력값의 NaN 검사

package thisisjava.chap03.num01;

public class InputDataCheckNaNExample1 {
    public static void main(String[] args) {
        String userInput = "NaN";
        double val = Double.valueOf(userInput);

        double currentBalcne = 10000.0;

        currentBalcne += val;
        System.out.println(currentBalcne);
    }
}

> NaN은 산술 연산이 가능하다는 점이 문제

> 사용자로부터 문자열을 입력받을 때에는 반드시 "NaN"인지 조사함

> 만약 "NaN"이라면 NaN과 산술 연산을 수행해서는 안 된다

 

 

package thisisjava.chap03.num01;

public class InputDataCheckNaNExample2 {
    public static void main(String[] args) {
        String userInput = "NaN";
        double val = Double.valueOf(userInput);

        double currentBalance = 10000.0;

        if (Double.isNaN(val)) {
            System.out.println("NaN이 입력되어 치리할 수 없음");
            val = 0.0;
        }
        currentBalance += val;
        System.out.println(currentBalance);
    }
}

> NaN인지 검사를 하려면 반드시 Double.isNaN()을 사용해야 함

 

 

 

'이것이 자바다' 공부 기록
300x250