본문 바로가기
공부/java

자바(java)의 연산(1)

by 샤샤샤샤 2023. 1. 23.

연산 우선 순위

 

사칙 연산에서 곱셈, 나눗셈이 덧셈, 뺄셈보다 우선 순위가 높듯이, 프로그램 연산에도 우선 순위가 존재한다.

 

그 순위는 다음과 같다.

 

단항 연산자 (++, --, !, ~)

비교 연산자 (<, >, <=, <=, ==, !=, <<, >>, >>>)

논리 연산자 (&&, ||, &, |, ^)

이항 연산자 (+, -, *, /, %)

삼항 연산자 (>, :)

대입 연산자 (=, +=, -=, *=, /=)

 

public class ex15 {
    public static void main(String[] args) {
        // 연산자
        // 연산자 우선순위 : 같은 줄에서 먼저 처리되는 순서
        // 예) int i = 3 * 2 + 10 / 5;  //출력값 8

        // 단항연산자 - 우선순위 높음
        // 이항연산자
        // 삼항연산자
        // 대입연산자 - 우선수위 낮음
        // * 연산자 우선순위 안외워도 됨
        // *헷갈리지 않으려면 먼저 처리될 연산자를 소괄호로 묶으면 됨.

        int i = (3*2) + ( 10/5 );
        System.out.println( i );

        // 이항연산자 : 산비논대(산성비가 논에 온대)
        // 단항 : ++ -- !(논리반전) (타입)            ~(비트반전)                      -우선 순위 높음
        // 산술 : + - * / %(나머지)                << >> >>>(비트단위 이동연산자)
        // 비교 : < > <= >= == !=
        // 논리 : &&(and) ||(or)                    & | ^(비트단위 논리연산자)
        // 삼항 : > :
        // 대입 : = 복합대입(+= -= *= /=)                                            -우선 순위 낮음

        // 단항 연산자 ++ -- !
        // ++ 증가 연산. 1이 증가되는 연산자.
        int k = 10;
        k++;    // k = k + 1
        System.out.println( k );

        //-- 감소 연산. 1이 감소되는 연산자.
        k--;   // k = k - 1
        System.out.println( k );

        // 논리반전 연산자 : ! (not)
        // true -> false false -> true
        boolean myBool = true;
        System.out.println(!myBool ); // false
        System.out.println(!!myBool ); // ture
    }

 

단항 연산자

1. ++, --

이 둘은 각각 1을 더하거나 뺀다는 의미다.

int k = 10;
k++;    // k = k + 1
System.out.println( k );                     결과:11

 

그러나 이 연산자는 앞에 붙느냐, 뒤에 붙느냐에 따라 그 의미가 달라진다.

 

i = 10;
System.out.println( i++ );        결과: 10
System.out.println( i );          결과: 11
System.out.println( ++i );        결과: 12
System.out.println( i );          결과: 12

차이가 보이는가?

 

변수 뒤에 붙은 ++ 는, 줄이 바뀌고 난 뒤에야 결과가 바뀐다.

연산은 끝났으나, 그 결과를 적용하지 않고 기다리다가, 줄이 바껴야지만 결과를 적용하는 것이다.

 

이렇게 헷갈리는 연산자는 좋은 연산자가 아니다.

코드는 복잡하면 안된다. 간결하고, 깔끔하며, 직관적이여야 좋은 코드다. 이 연산자는 너무 헷갈려 최신 언어들에서는 삭제되었다.

 

2. ! (논리반전)

코딩의 세계에서 !는 부정을 의미하며, 부정하고자 하는 대상 앞에 쓴다.

!는 논리반전 연산자로 불리언(boolean)형식에 쓰인다.

boolean z = true;
System.out.println(z);        결과: true
System.out.println(!z);       결과: false

 3. ~ (비트반전)

비트단위에서 쓰이는 연산자로 잘 쓰이지는 않으나 컴퓨터 로직을 이해하는데 도움이 될것 같아서 정리한다.

~ 는 모든 비트를 반전시킨다.

 

예를 들어보자.

1바이트에 숫자 1을 저장하면 컴퓨터는 다음과 같은 2진법으로 저장한다.

 

0 0000001

 

여기서 가장 앞의 0은 이 숫자가 양수임을 의미한다. 음수는 1이 된다.

이 이진수를 ~를 이용해 반전시키면 다음과 같이 된다.

 

1 1111110

 

즉, ~는 비트 단위에서 0을 1로, 1을 0으로 변경시킨다.

그렇다고 데이터 1이 -1이 되는 건 아니다.

 

int i = 1; 

i = ~i;   // 0 0000.....001111  => 1 1111....11000
System.out.println( i );         결과 : -2

이를 이해하기 위해서는 2의 보수를 알아야 한다.

 

이는 필자도 확실하게 이해하지 못한 개념임으로, 혼동을 줄이고자 넘어간다.

다만 비트단위에서 계산을 쉽게 하기 위해 도입된 개념이라고만 알고 있으면 된다.

public class ex17 {
    public static void main(String[] args) {
        // 비트단위 연산자 : 잘 안쓰임
        // ~ 연산자 : 비트반전 연산자 0 -> 1  1 -> 0
        // 논리반전 연산자 (!) 와 헷갈리지 말것
        //           true -> false    false -> true

        int i = 1; // 이진수로 하면 1111, 메모리에 저장되는 형식은 0 0000....001111 (프로그램이 자체적으로 앞의 0을 제거해서 출력)
        System.out.println( Integer. toBinaryString( i ));

        i = ~i;   // 0 0000.....001111  => 1 1111....11000
        System.out.println( Integer. toBinaryString( i ));
        System.out.println( i );

    }
}

 

3. 산술연산자

+, -, *, /, %

 

워낙 친숙한 계산들이다 보니 딱히 설명할 거리는 없다. 먼저 계산하고자 하는 연산을 ()괄호로 묶어주면 되는것 마저 우리 상식과 똑같다. 곱하기, 나누기 우선인 것도 마찬가지.

다만 /, %는 정수 영역에서 계산되는 부호들로, 각각 몫, 나머지를 구해준다는 것만 기억하자.

실수형의 값을 구하고 싶다면 피연산자중 하나를 실수형으로 선언하고 계산하면 된다.

 

올림, 내림, 반올림.

 

파이썬을 공부할 때 파이썬에서는 반올림이 안된다고 들었던 것 같은데, 자바는 가능하다.

두가지 방식이 존재한다.

따로 import하지 않고도 사용 가능한 Math클래스의 함수를 사용하거나, 실수형 -> 정수형 의 과정에서 이뤄지는 소수점 탈락을 이용하는 것이다.

 

내림

double doubleFloor = 3.14;
int intFloor = (int)doubleFloor;
System.out.println(intFloor);                       결과 : 3
System.out.println(Math.floor(doubleFloor));        결과 : 3

 

int intFloor = (int)doubleFloor;

 

이 코드는 실수형인 doubleFloor을 강제로 정수형 int로 형변환을 일으켜 소수를 탈락시킨 것이다.

반면 Math.floor(doubleFloor)는 자바에서 지원하는 Math 클래스의 내림 기능 floor을 이용한 것이다.

 

올림

double doubleCeil = 3.14;
int intCeil = (int)(doubleCeil + 1.0);
System.out.println(intCeil);
System.out.println(Math.ceil(doubleCeil));
int intCeil = (int)(doubleCeil + 1.0);

이 코드 역시 실수형 -> 정수형 규칙을 사용했다.

숫자 1을 더하고 소수점을 탈락시켰다.

올림을 위한 Math 클래스 기능은 ceil이다.

 

반올림 

double doubleRound = 3.5;
int intRound = (int)(doubleRound + 0.5);
System.out.println(intRound);
System.out.println(Math.round(doubleRound));

반올림은 1이 아닌 0.5를 더한다.

만약 소수점이 0.5 이상이라면 해당 수의 정수부분은 1이 증가할 것이고, 이를 강제형변환을 통해 소수점을 없애주면 된다.

Math클래스의 반올림 메서드는 round이다.

 

public class ex19 {
    public static void main(String[] args) {
        // 소숫점 버림, 반올림, 올림
        // 소수점 첫째자리 버림 : 3.14 -> 3.0
        //              반올림 : 3.14 -> 3.0     3.5 -> 4.0
        //              올림 : 3.14 -> 4.0
        // 버림: 형변환 연산자로 구현 가능. 소수점 탈락을 이용
        //       Math.floor함수 이용
        double doubleFloor = 3.14;
        int intFloor = (int)doubleFloor;
        System.out.println(intFloor);
        System.out.println(Math.floor(doubleFloor));

        // 반올림 : (피연산자 + 0.5) 한 뒤 형변환
        //          Math.round 함수 이용
        // 3.14 => 3.0         3.14 + 0.5 = 3.64   --------- 소수점 날아가면 3
        // 3.5 => 4.0          3.5 + 0.5 = 4.0     --------- 소수점 날아가면 4
        double doubleRound = 3.5;
        int intRound = (int)(doubleRound + 0.5);
        System.out.println(intRound);
        System.out.println(Math.round(doubleRound));

        // 올림 : (피연산자 + 1.0) 한 뒤 형변환
        //        Math.ceil함수 이용

        double doubleCeil = 3.14;
        int intCeil = (int)(doubleCeil + 1.0);
        System.out.println(intCeil);
        System.out.println(Math.ceil(doubleCeil));
    }

마지막으로 내가 고민했던 연습 문제를 올리겠다.

import java.util.Scanner;
public class ex20 {
    public static void main(String[] args) {
        // 연습문제8
        // 1. 콘솔로 부터 3.141592를 입력받고
        //    소수점 첫째자리에서 반올림하고 출력하시오.
        // 2. 소수점 첫째자리에서 올림하고 출력하시오.
        // 3. 소수점 첫째자리에서 버림하고 출력하시오.

        // 4. 콘솔로부터 3.561을 입력받고
        //    소수점 둘째자리에서 반올림하고 출력하시오.
        // 5. 소수점 둘째자리에서 올림하고 출력하시오.
        // 6. 소수점 둘째자리에서 버림하고 출력하시오.

        //1.
        Scanner scan = new Scanner(System.in);
        System.out.println("숫자를 입력하시오.");
        double num1 = scan.nextDouble();
        double num2 = num1 + 0.5;
        System.out.println((int)num2);
        //2.
        System.out.println((int)(num1 + 1.0));
        //3.
        System.out.println((int)num1);
        //4.
        System.out.println("숫자를 입력하시오.");
        double num3 = scan.nextDouble();
        double num4 = num3 * 10;
        double num5 = (int)( num4 + 0.5);  // num5를 int로 선언하면 안됨
        System.out.println( num5 / 10 );   // 정수형 / 정수형 = 정수형으로 나오기 때문에, 3.561을 넣었을때
        //5.                               // 자동적으로 출력값도 int형태로 나옴. 그래서 소수점이 날아감.
        num5 =(int)(num4 + 1);             // 정 num5 첫 선언에 int로 하고 싶으면 출력값이나 10을 실수로
        System.out.println( num5 / 10 );   // 지정하자. 한참 고민했네......
        //6.
        num5 = (int)(num4);
        System.out.println( num5 / 10);
        scan.close();

(참고로

 

num3 => num1

num4=>num2

num5 => double num3로 선언

 

위 처럼 재할당, 초기화해서 코드를 더 깔끔하게 만들 수 있다.)

'공부 > java' 카테고리의 다른 글

자바(java)의 난수(랜덤수) 출력  (0) 2023.01.23
자바(java)의 조건문(1)  (1) 2023.01.23
자바(java)의 버퍼 메모리  (0) 2023.01.23
자바 데이터 타입 변환(형변환)  (0) 2023.01.22
자바(java)의 데이터 타입  (0) 2023.01.22