실수 표현 방식
실수를 컴퓨터에서 표현하는 방식으로는 대표적인 고정 소수점 방식과 부동소수점 방식으로 나눌 수 있다.
- 메모리는 한정적이기 때문에 컴퓨터는 소수를 이진법으로 표현할 떄 고정 소수점 방식이 아닌 부동 소수점 방식을 이용한다.
고정 소수점 방식(Fixed-Point Number Representation)
- 고정 소수점 방식은 메모리를 정수부와 소수부로 고정으로 나누어 지정하여 처리하는 방식이다.
- 고정소수점 방식은 소수부의 자릿수를 미리 정하고 고정된 자릿수의 소수를 표현하기 떄문에 직관적이다.
10진수로 표현된 실수를 이진수로 변환하고 결과 값을 각각 정수부, 소수부 메모리 비트에 넣어주기만 하면 표현이 된다.
- 직관적적으로 메모리에 실수를 표현할 수 있다는 장점이 있지만, 정수부가 큰 실수가 있을수도 있고 반대로 소수박 큰 실수다 있을수도 있기 때문에 표현 가능한 범위가 매우 적다는 단점이 있다.
부동 소수점 방식(Floating-Point Number Representation)
부동 소수점 방식은 소수점(poing)이 떠다닌다(floating)라는 의미이다.표현할 수 있는 값의 범위를 넓혀 오차를 줄이고자는 시도에서 탄생하였다.
- 정수부와 소수부로 나누던 고정 소수점 방식과는 달리 지수부와 가수부로 나눈다.
실수의 값 자체를 가수부(23bit)에 넣어서 표현한다.
- 정수부가 크든 소수부가 크든 상관없이 가수부에서 전체 실수를 표현하기 떄문에 공간 낭비 문제가 해결 되며 고정 소수점 방식에 비해 큰 범위 값을 값을 표현할 수 있다.
지수(e) 표기법?
- 지수 표기법은 숫자를 지수 형태로 표기하여 무의미한 0이나 소수점을 생략할 수 있다.
- 지수 표기법은 아주 큰 숫자나 아주 작은 숫자를 간단하게 표기할 떄사용되는 표기법이다.
- e는 밑수 10을 의미하며 대문자로 쓸 수도 있다.
- 지수는 밑수(e) 옆에 숫자로 표기한다(+는 생략 가능)
- 정규화 표기법 : 임의의 실수의 절댓값을 1이상 10미만으로 설정하는것을 정규화 표기법이라고 한다.
31,400,000,000 -> 3.14 * 10^10 -> 3.14e10
0.00314 -> 3.14 * 10^-3 -> 3.14e-3
- 큰 범위의 값을 표현 가능하기 떄문에 자바에서 사용하는 정수 타입들의 범위 보다 실수 타입의 범위가 훨씬크다.
- '변수의 타입의 범위 < 리터럴 타입의 범위'에 포함 되므로 에러가 발생한다.
long L = 3.14f
부동 소수점 방식을 사용하면 매우 큰 범위의 실수까지도 표현할 수 있어 보다 정밀하게 소수를 표현할수는 있지만 그래도 완전히 정확하게 표현하는 것이 아니다.
컴퓨터의 실수 연산은 소수점 단의 값을 정확히 표현하는 것이아니라 근사값으로 처리하기 떄문에 오차가 발생하는 것이다.
- 이런 오차는 소수를 연산하는데 부정확한 결과값이 발생하고 또다시 오차를 유발한다.
부동 소수점 계산
자바는 IEEE 754 표준 방식을 따르고 부동 소수점 방식은 하나의 실수를 가수부와 지수부로 나누어 표현한다.
±(1.가수부)×2^지수부-127
아래는 실수를 부동 소수점으로 변환하는 예시이다.(float 기준)
1. 부호비트를 설정, 음수이면 1 양수이면 0이다.
- double의 가수는 53bit이다.
2. 10진수로 표현된 실수를 이진수로 변환
100.5 => 1100100.1
3. 정규화를 통해 정수부가 한자리가 되도록 변환, 지수를 사용하여 표현(부동 소수점)
- 정규화 : 소수점을 이동 시키는 것
1100100.1 => 1.1001001 * 2^6
// ±(1.가수부)×2^지수부-127
4. 가수부 에 소수점 아래 부분의 실수 값 그대로 넣는다. 나머지는 0으로 채운다.

지수에 bias(기저, 127)을 더하고 이진수로 변환후, 지수부 비트에 넣는다.
- double : 1023
- float : 127
(지수부)6 + 127 => (10)133 => (2)10000101
지수의 값에 왜 bias를 더해줄까?
지수의 값이 음수가 될 수 있기 bias를 더해준다.
- 10진수로 표현된 실수(0.625)를 이진수로 변환했을 때 0.101가 된다.
(10) 0.625 => (2)0.101
- 0.101를 정규화를 하게 되면 지수가 음수인 1.01 * 2^-1가 된다.
(2)0.101 => (정규화) 1.01 *2^-1
- 음수 지수(-1)를 8비트로 표현하기 위해 127을 더해준다.
(지수부)-1 + 127 => (10)126 => (2)1111110
- 8bit로는 256 개의 수를 표현할 수 있는데, 양/음수를 표현하기위해 일단 지수에서 127을 더해 음수는 (0 ~ 127) 까지, 양수는 (128 ~ 155) 까지 구분하기 위해서이다.
- 따라서 지수에 bias 값을 한 값 이 127 이하면 음수, 크면 양수로 구분할 수 있다.
정밀도
자바에서 실수를 표현하는데 타입별로 정밀도가 있다. 정밀도가 결정나는 이유는 부동소수점 표현 방식에 따른 결과로, 가수부를 표현할 수 있는 크기에 따라 결정되기 떄문이다.
논리형 타입 | 크기 | 표현범위 | 정밀도 | |
float | 4 byte | ±(1.40129846432481707e-45 ~ 3.40282346638528860e+38) | 7 | |
double | 8 byte | ±(4.94065645841246544e-324d ~ 1.79769313486231570e+308d) | 15 |
- float형은 가수의 길이가 23 bit 이지만 정규화를 통해 실제로는 24자리 까지 저장할 수 있다. 2^24는 10^7보다 크고 10^8보다 작기 때문에 정밀도는 7이된다.
- double형은 가수의 길이가 52 bit 이지만 정규화를 통해 실제로는 53자리 까지 저장할 수 있다. 2^53은 10^15보다 크고 10^16보다 작기 떄문에 정밀도가 15이다.
- 정밀도가 7이라는 것은 7자리의 10진수를 오차없이 정확하게 표현할 수 있다는 뜻이다. 마찬가지로 정밀도가 15이라는 것은 15자리의 10진수를 오차없이 정확하게 표현할 수 있다는 뜻이다.
- float을 사용하여 연산속도 향상이나 메모리의 절약을 필요로 하는경우가 아니라면보다 높은 정확도를 필요로 할 경우 double 타입을 사용하면 된다는 것이다.
'Java' 카테고리의 다른 글
[JAVA] 네트워킹(Networking) (0) | 2024.03.14 |
---|---|
[JAVA] 스트림(Stream) API(4, Collectors, 그룹화와 분할) (0) | 2024.03.14 |
[JAVA] 스트림(Stream) API(3, 최종 연산) (0) | 2024.03.09 |
[JAVA] 스트림(Stream) API(2, 중간 연산, Optinal<T>) (0) | 2024.02.29 |
[JAVA] 스트림(Stream) API(1) (0) | 2024.02.25 |