Java 기본형 5

2021. 6. 2. 18:00Java

실수형의 저장형식

앞서 언급한 바와 같이 실수혀은 정수형과 표현형식이 달라서, 실수형은 값을 부동소수점수의 형태로 저장한다. 부동소수점수는 실제 +-M x 2의 E제곱 와 같은 형태로 표현하는 것을 말하며, 부동소수점수는 부호(Sign), 지수(Exponent), 가수(Mantissa), 모두 세 부분으로 이루어져 있다.

float과 double의 표현형식

  1. 부호(Sign bit)
    S는 부호비트를 의미하며, 1bit이다. 이 값이 0이면 양수를 1이면 음수를 의미한다. 정수형과 달리 2의 보수법을 사용하지 않기 떄문에 양의 실수를 음의 실수로 바꾸려면 그저 부호비트만 0에서 1로 변경하면 된다.
  2. 지수(Exponent)
    E는 지수를 저장하는 부분으로 float의 경우, 8bit의 저장공간을 갖는다. 지수는 '부호있는 정수'이고, 8bit로는 모두 2의8승(256)개의 값을 저장할 수 있으므로, -127 ~ 128의 값이 저장된다. 이 중에서 -127과 128은 숫자 아님(Not a Number)이나 양의 무한대(POSITIVE_INFINITY), 음의 무한대(NEGATIVE_INFINITY)와 같이 특별한 값의 표현을 위해 예약되어 있으므로 실제로 사용가능한 지수의 범위는 -126 ~ 127이다. 그래서 지수의 최대값이 127이므로 float타입으로 표현할 수 있는 최대값은 2의127승이고, 10진수로 10의38승이다. 그러나 float의 최소값은 가수의 마지막자리가 2의-23승이므로 지수의 최소값보다 2의-23배나 더 작은 값, 약 10의-45승이다.
  3. 가수(Mantissa)
    M은 실제 값인 가수를 저아하는 부분으로 float의 경우 2진수 23자리를 저장할 수 있다. 2진수 23자리로는 약 7자리의 10진수를 저장할 수 있는데 이것이 바로 float의 정밀도가 된다. double은 가수를 저장할 수 있는 공간이 52자리로 float보다 약 2배이므로 double이 float보다 약 2배의 정밀도를 갖는 것이다.

부동소수점의 오차

실수 중에서 파이와 같은 무한소수가 존재하므로 정수와 달리 실수를 저장할 때는 오차가 발생할 수 있다. 게다가 10진수가 아닌 2진수로 저장하기 때문에 10진수로는 유한소수이더라도 2진수로 변환하면 무한소수가 되는 경우도 있다. 2진수로는 10진 소수를 정확히 표현하기 어렵기 때문이다.

 

9.1234567 → 1001.000111111001101011011011...

 

이처럼 알 수 있듯이 9.1234567은 10진수로 유한소수지만, 2진수로는 무한소수이다. 즉 2진수로는 이 값을 정확히 표현하지 못한다는 얘기다. 여기서부터 벌써 오차가 발생한다. 비록 2진수로 유한소수라도 가수를 저장할 수 있는 자리수가 한정되어 있으므로 저장되지 못하고 버려지는 값들이 있으면 오차가 발생한다. 2진수로 변환된 실수를 저장할 떄는 먼저 1. xxx X 2^n의 형태로 변환하는데, 이 과정을 정규화라고한다.

 

1001.000111111001101011001111... 정규화 → 1.001000011111001101011011011.... X 2^3

 

정규화된 2진 실수는 항상 1. 으로 시작하기 떄문에 1. 을 제외한 23자리의 2진수가 가수(Mantissa)로 저장되고 그 이후는 잘려나간다. 지수는 기저법으로 저장되기 떄문에, 지수인 3에 기저인 127을 더한 130이 2진수로 변환되어 저장된다. 10진수 130은 2진수로 10000010이다.

FloatToIntBits 예제
출력결과

Float클래스의 floatToIntBits()는 float타입의 값을 int타입의 값으로 해석해서 반환한다. 반환된 값을 16진수로 출력하면 float타입의 값이 2진수로 어떻게 저장되는지 확인할 수 있다. 실행결과를 보면, 앞서 설명한 것과 달리 0x4111F9AE이다. 그이유는 잘려나간 첫 번쨰 자리의 값이 1이라서 반올림되어 0x4111F9AD의 2진수 마지막자리 두 자리의 값이 01에서 10으로 1증가 했기 떄문이다.

10진수와 달리 2진수는 1이면, 반올림한다. 2진수에서는 1이 절반이기 떄문이다.

'Java' 카테고리의 다른 글

Java 2의보수법  (0) 2021.06.10
Java 기본형 4  (0) 2021.06.01
Java 기본형 3  (0) 2021.05.31
Java 기본형 2  (0) 2021.05.30
Java 기본형  (0) 2021.05.29