Java 기본형 3

2021. 5. 31. 18:00Java

실수형 - float, double

실수형의 범위와 정밀도

실수형은 실수를 저장하기 위한 타입으로 float와 double, 두 가지가 있으며 각 타입의 변수에 저장 할 수 있는 값의 범위는 아래와 같다.

위 표의 범위는 양의 범위만 적은 것으로, 이 범위에 -부호를 붙이면 음의 범위가 된다. 예를 들어 float타입으로 표현가능한 음의 범윈는 -1.4 x 10의-45승 ~ -3.4 x 10의38승이다. float타입으로 표현가능한 양의 범위와 음의 범위를 함께 그림으로 그리면 다음과 같다.

float타입으로 표현할 수 있는 값의 범위

즉, float타입의 표현범위는 -3.4 x 10의 38승 ~ 3.4 x 10의 38승이지만 -1.4 x 10의-45승 ~ 1.4 x 10의45승 범위(0은 제외)값은 표현할 수 없다. 실수형은 소수점수도 표현해야 하므로 얼마나 큰 값을 표현할 수 있는가 뿐만 아니라 얼마나 0에 가깝게표현할 수 있는가도 중요하다.

Q. 실수형도 정수형 처럼 저장할 수 있는 범위를 넘게 되면 오버플로우가 발생하나요?

A. 앞서 정수형에서 변수의 값이 표현범위를 벗어나는 것은 오버플로우라고 배웠습니다. 정수형에서도 변수의 값이 표현범위의 최대값을 벗어나면 오버플로우가 발생하는데요. 정수형과 달리 실수형에서는 오버플로우가 발생하면 변수의 값은 무한대가 됩니다. 그리고 정수형에는 없는 언더플로우가 있는데,
언더플로우는 실수형으로 표현할 수 없는 아주 작은 값, 즉 양의 최소값보다 작은 값이 되는 경우를 말합니다.
이 때 변수의 값은 0이 됩니다.

 

4byte의 정수로는 약 +- 2 x 10의9승의 값밖에 표현할 수 없는데, 어떻게 같은 4byteㄹ호 +-3.4 x 10의38승과 같이 큰 값을 표현할 수 있는 것일까? 그 이유는 값을 저장하는 형식이 다르기 때문입니다.

int타입과 float타입의 표현형식

위 그림은 int타입과 float타입의 표현형식을 비교한 것인데, int타입은 부호와 값, 구 부분으로 이루어져있지만, float타입과 같은 실수형은 부호(S), 지수(E), 가수(M). 세 부분으로 이루어져 있다. 즉, 2의 제곱을 곱한 형태로 저장하기 때문에 이렇게 큰 범위의 값을 저장하는 것이 가능한 것이다. 그러나 정수형과 달리 실수형은 오차가 발생 할 수 있다는 단점이 있다. 그래서 실수형에는 표현할 수 있는 값의 범위뿐만 아니라 '정밀도(Precision)'도 중요한 요소이다. 실수형의 범위와 정밀도표를 보면 float타입은 정밀도가 7자리인데, 이것은 a x 10의n승(1 ≤ a < 10)의 형태로 표현된 7자리의 10진수를 오차없이 저장할 수 있다는 뜻으로 아래의 세 값은 float타입의 변수에 저장했을 때 오차없이 저장할 수 있다.

1234.567 = 1.234567 x 10의3승
0.00001234567 = 1.234567 x 10의-5승
1234567000 = 1.234567 x 10의9승

 

만일 7자리 이상의 정밀도가 필요하다면, 변수의 타입을 double로 해야 한다. double타입은 float타입보다 정밀도가 약 2배인 10진수로 15자리의 정밀도를 가지므로 float타입보다 훨씬 더 정밀하게 값을 표현할 수 있다. 실수형 값을 저장할 때, float타입이 아닌 double타입의 변수를 사용하는 경우는 대부분 저장하려는 값의 범위때문이 아니라 보다 높은 정밀도가 필요해서이다.

double이라는 이름은 float보다 약 2배(double)의 정밀도를 갖는다는 의미에서 붙여진 것이다.

 

연산속도의 향상이나 메모리를 절약하려면 float를 선택하고, 더 큰 값의 범위라던가 더 높은 정밀도를 필요로 한다면 double을 선택해야 한다.

float, double 예제
출력결과

실수형 값을 출력할 때는 printf메서드의 지시자 %f를 사용해야한다. %f는 기본적으로 소수점 이하 6자리까지만 출력하므로, 7번째 자리에서 반올림되어 9.123457이 되었다.

앞서 배운 것처럼, %24.20f는 전체 24자리 중에서 20자리는 소수점 이하의 수를 출력하라는 뜻이다.

실제로 저장된 값은 9.123456954956055인데, 앞뒤에 빈자리가 공백과 0으로 채워진 것을 알 수 있다.

 

9.12345678901234567890 - 원래값

9.12345695495605500000 - 저장된 값

 

float타입의 변수로 f에 저장하려던 원래의 값은 9.12345678901234567890이지만 저장공간의 한께로 오차가 발생하여 실제 저장된 값은 9.1234569549560550000이다.

그러나 이 두 값이 앞의 7자리는 일치한다. 정림도가 7자리이므로 원래의 값에서 7자리의 값만 오차없이 저장된 것이다.

간혹 원래 값과 8자리 이상 일치하는 경우도 있지만 항상 그런것은 아니기 떄문에 이런 결과를 기대해선 안된다.

'Java' 카테고리의 다른 글

Java 기본형 5  (0) 2021.06.02
Java 기본형 4  (0) 2021.06.01
Java 기본형 2  (0) 2021.05.30
Java 기본형  (0) 2021.05.29
Java 진법 4  (0) 2021.05.28