-
[Java] float과 double의 차이는 무엇일까?Language/Java 2021. 1. 25. 17:43728x90반응형
float vs double의 차이는?
float과 double 모두 실수를 표현하기 위해 사용하는 자료형이라는 것은 알고 있을 것 입니다. 하지만 정확한 차이가 무엇이냐고 물어본다면 대답하기가 쉽지 않습니다...(애매하게 float은 4byte, double은 8byte다 이정도..)
위에서 볼 수 있듯이
float은 4Byte
,double은 8byte
입니다. 실수형 데이터 타입을 다룰 때 중요한 것은정밀도(precision)
입니다.정수형보다 실수형을 쓰면 훨씬 더 큰 값을 표현할 수 있지만,
오차
가 발생할 수 있다는 단점이 있습니다.유효자릿수
가 뜻하는 것은정밀도
를 뜻합니다. 즉, 몇자리 까지 오차없이 표현할 수 있는가입니다. float은 7자리, double은 15~16자리 까지 표현할 수 있습니다.따라서
float
의 정밀도보다 더 높은 정밀도가 필요하다면double
을 사용해야 합니다.위의 그림을 보시면 실수형 범위에서 표현할 수 없는 범위가 있는 것을 볼 수 있습니다. 실수형은
얼마나 큰 값을 표현할 수 있는가 뿐만 아니라 얼마나 0에 가깝게 표현할 수 있는가
도 중요합니다.(얼마나 정밀도 있게 표현할 수 있는가라고도 할 수 있습니다.)실수형의 저장 방식
4 byte의 정수로는
약 +-2x10^9
의 값밖에 표현할 수 없는데, 어떻게 같은 4 byte로+-3.4x10^38
과 같이 큰 값을 표현할 수 있는 걸까요?
그 이유는바로 값을 저장하는 형식이 다르기 때문
입니다.int형은 32비트 중 1비트=부호비트, 31비트는 값을 표현하는데 사용합니다.
float
과double
은 위와 같이부호(S)
,지수(E)
,가수(M)
로 나눠서 표현하게 됩니다.단일-정밀도(single-precision number) 형식: 32비트로 표현된 부동소수점 수 (float) 복수-정밀도(double-precision number) 형식: 64비트로 표현된 부동소수점 수 (double)
즉,
+-M x 2^E
형태로 저장하기 때문에 이렇게 큰 범위의 값을 저장하는 것이 가능한 것입니다.예시를 들어서 어떻게 표현하는지 한번 알아보겠습니다.
274,000,000,000,000
은2.74 x 10^14
으로,0.00000000000274
는2.74 x 10^-12
로 표현할 수 있습니다.
여기서 소수점의 위치를지수(exponent)
로 표현할 수 있습니다. 예시의 경우는 14와 -12가 지수입니다.이와 같이 소수점의 위치를 필요에 따라 이동시키는 표현 방법을
부동소수점 표현(floating-point representation)
이라고 하며, 그와 같이 표현된 수를부동소수점 수(floationg-point number)
라고 부릅니다.그래서 다시 2.74 x 10^14의 경우에는
가수(M) = 2.74
,지수(E) = 14
,부호는 양수면 1, 음수면 0
입니다.
(다만, 디지털 컴퓨터에서는 2진수 체계가 사용되기 때문에 2진 부동소수점 수로 사용되고 지수(E)의 밑이 10이 아니라 2로 바뀌게 됩니다.)가수(Mantissa): 실제 값을 저장하는 부분
지수(Exponent): 부호있는 정수
부호(Sign bit): 0이면 양수, 1이면 음수
0.1101 x 2^5
11.01 x 2^3
0.001101 x 2^7위와 같이 통일되지 않아 혼란이 일어나기 때문에 아래와 같이 정규화된 표현이 있습니다.
소수점의 바로 오른 편에 있는 비트가 반드시 '1'이 되도록 위치를 조정하는 것을 말합니다.1.101 x 2^4
0.1101 x 2^9위와 같이 변경할 수 있습니다.
따라서 실제로 위와 같은 형태로 저장이 됩니다. (자세히 설명하면 엄청 복잡하지만,, 일단은 이정도에서 마무리..)
- 가수(M) = 1.101101 이기 때문에 가수를 저장할 수 있는 비트가 많은 수록 정밀도는 높아질 것입니다.
- 지수(E) = 지수는 3이기 때문에 지수를 지정할 수 있는 비트가 많을 수록 값을 표현할 수 있는 범위가 커질 것입니다.
따라서
가수
,지수
를 적절하게 분배해야 정밀도, 값의 크기를 효율적으로 표현할 수 있습니다.부동 소수점 오차
실수 중에는
파이(3.141592...)
와 같이 무한소수가 존재하므로, 정수와 달리 실수를 저장할 때는 오차가 발생할 수 있습니다.게다가 10진수가 아닌 2진수로 저장하기 때문에 10진수로는 유한소수이더라도, 2진수로 변환하면 무한소수가 되는 경우도 있습니다.
10진수: 9.1234567 2진수: 1001.000111111001101011011011... 정규화: 1.001000111111001101011011011...
위와 같이 10진수일 때 유한소수인 것을 2진수로 바꾸면 무한소수가 됩니다. 이제 위에서 실수형의 저장하는 형식을 보았던 것을 대입해보겠습니다.
- float 자료형을 사용 = 32비트 (부호(1비트), 지수(8비트), 가수(23비트))
- 여기서
1.001000111111001101011011011...
이러한 무한소수를 모두 저장할 수 없기 때문에 이 중에서 23비트만을 저장합니다. - 이렇게 짤리는 부분 때문에 오차가 생기게 됩니다. (코드로 확인을 해보겠습니다.)
public class Test { public static void main(String[] args) { float f = 9.1234567f; System.out.println(f); // 9.123457 } }
위의 결과를 보면 알 수 있듯이 마지막 7이 짤리고 6은 반올림 된 것을 확인할 수 있습니다. 이제 다시 어느정도
float
,double
의 차이를 알 수 있을 것입니다.반응형'Language > Java' 카테고리의 다른 글
[Java] equals()를 재정의 하려거든 hashCode()도 재정의 해야 하는이유 (0) 2021.01.26 [Java] ArrayList와 Vector 클래스의 차이는? (0) 2021.01.26 [Java] HashMap vs Hashtable 차이는 무엇일까? (1) 2021.01.25 [Java] String vs StringBuilder vs StringBuffer 차이는? (0) 2021.01.25 [Java] BigDecimal 클래스란 무엇일까? (0) 2021.01.25