ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 산술 변환
    Java/연산자 2020. 10. 19. 22:53

     

     

     

     

    이항 연산자는 두 피연산자의 타입이 일치해야 연산이 가능하므로, 피연선자의 타입이 서로다르다면 연산 전에 형변환 연산자로 타입을 일치시켜야한다.

    이처럼 연산 전에 피연산자 타입의 일치를 위해 자동 형변환되는 것을 '산술 변환' 또는 '일반 산술 변환'이라하며, 이 변환은 이항 연산에서만 아니라 단항 연산에서도 일어난다. 

     

    '산술 변환'의 규칙은 다음과 같다.

     

    1. 두 피연산자의 타입을 같게 일치시킨다. (보다 큰 타입으로 일치) - 피연산자의 값손실을 최소화하기 위한 것

     

         long + int    --->   long + long    --->   long

         float + int    --->   float + float    --->   float

         double + float   --->   double + double   --->   double

     

     

    2. 피연산자의 타입이 int보다 작은 타입이면 int로 변환된다.

        - char, short의 표현범위가 좁아서 연산중에 오버플로우(overflow)가 발생할 가능성이 높기 때문

     

         byte + short    --->   int + int   --->  int

         char + short    --->   int + int   --->  int

     

     

    연산결과의 타입은 피연산자의 타입과 일치한다. 예를들어 int와 int의 나눗셈 연산결과는 int이다.

     

    int   /   int   -->   int

     5   /    2    -->   2

     

    그래서 5 / 2의 결과가 2.5가 아닌 2이다. 위의 식에서 2.5라는 실수를 결과로 얻으려면, 피연산자 중 어느 한 쪽을 float와 같은 실수형으로 형변환해야 한다. 그러면, 다른 한 쪽은 일반 산술 변환의 첫 번째 규칙에 의해 자동적으로 형변환되어 두 피연산자 모두 실수형이 되고, 연산 결과 역시 실수형의 값을 얻을 수 있다. 

     

     

    int   /   (float) int   -->   int / float   -->   float / float   --> float

     5   /    (float) 2    -->     5 / 2.0f    -->    5.0f / 2.0f     --> 2.5f

     

     

     

     

     

     

     

     

     

     아래의 코드를 보면 컴파일 에러가 발생한다. 명시적으로 형변환이 필요하다. --> a와 b는 모두 int형보다 작은 byte 형이기 때문에 연산자 '+'는 이 두개의 피연산자들의 자료형을 int형으로 변환한 다음 연산(덧셈)을 수행한다.
      그래서 'a + b'의 연산결과는 byte 형이 아닌 int형(4byte)인 것이다. 4byte의 값을 1byte의 변수에 형변환없이 저장하려고 했기 때문에 에러가 발생하는 것이다.

     

     

     

     

    크기가 작은 자료형의 변수를 큰 자료형의 변수에 저장할 때는 자동으로 형변환(type conversion, casting)되지만, 반대로 큰 자료형의 값을 작은 자료형의 변수에 저장하려면 명시적으로 형변환 연산자를 사용해서 변환해주어야 한다.

     

     

    10 * 30의 결과는 300이지만, 형변환(캐스팅, casting)에서 배운 것처럼 큰 자료형에서 작은 자료형으로 변환하면 데이터의 손실이 발생하므로 값이 바뀔 수 있다. 300은 byte형의 범위를 넘기 때문에 byte형으로 변환하면 데이터 손실이 발생하여 결국 44가 byte형변수에 c에 저장된다.

     

     

     

     

     

     

    위의 식 'a * b'의 결과 값을 담는 변수 c의 자료형이 long타입(8byte)이기 때문에 2x10^12 을 저장하기에 충분하므로 '2000000000000'이 출력될 것 같지만, 결과는 전혀 다른 값이 출력된다.

    그 이유는 int타입과 int타입의 연산결과는 int 타입이기 때문이다.

    'a * b'의 결과가 이미 int 타입의 값(-1454759936)이므로 long 형으로 자동 형변환되어도 값은 변하지 않는다.

     

           long c = a * b;

    -->   long c = 1000000 * 2000000;

    -->   long c = -1454759936;

     

     

    올바른 결과를 얻으려면 아래와 같이 변수 a 또는 b의 타입을 'long'으로 형변환해야 한다.

     

           long c = (long) a * b;

    -->   long c = (long) 1000000 * 2000000;

    -->   long c = 1000000L * 2000000;

    -->   long c = 1000000L * 2000000L;

    -->   long c = 2000000000000L;

     

     

     

     

     

     

     

     

     

     

     

         int                 int                              int

    1000000     *    1000000          --->     -727379968            overflow 발생

     

     

         int                int                               long                long                              long

    1000000     *    1000000L         --->       1000000L     *   1000000L        --->     1000000000000L

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    [참고 도서 Java의 정석_기초편] http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788994492049&orderClick=LEa&Kc=

    'Java > 연산자' 카테고리의 다른 글

    나머지 연산자  (0) 2020.10.20
    Math.round( )로 반올림하기  (0) 2020.10.19
    사칙 연산자  (0) 2020.10.19
    형변환 연산자  (0) 2020.10.19
    부호 연산자  (0) 2020.10.19
Designed by Tistory.