Fear is a habit. I'm not afraid.
1과 1.0은 같은가? 본문
결론부터 말하자면,
1. 자바 프로그래밍에서 2. int형인 1과, float 1.0을 비교 연산자를 통해 비교하였을 때
같다.
자바 프로그래밍 기초 수업을 듣고 있는데, 비교연산자 예시에서 아래와 같은 예시를 보았다.
package javastudy;
public class Study17 {
public static void main(String[] args) {
int num3 = 1;
float num4 = 1.0f;
System.out.println(num3==num4);
}
}
결과
true
상식적으로는 1이랑 1.0이랑 값이 같으니 당연히 true가 나온다고 생각을 했다.
하지만 이것이 어떤 단계적 순서로 처리가 되는지 궁금해져서 찾아보았다.
비교 연산 순서
- 변수에 값 할당
- 비교 시 타입 확인
- 타입이 다르면 작은 타입을 큰 타입으로 자동 형변환
- 형변환된 값들끼리 비교 수행
1. 변수에 값 할당
int i = 1; // 정수 1이 i에 저장
float f = 1.0f; // 실수 1.0f가 f에 저장
2. 비교 시 타입 확인
비교 연산자( == ) 를 만나면, 타입 비교 후 형변환
Java에서는 int 보다 float 의 표현 범위가 더 크므로 int에서 float 로 자동 형변환 발생
(float)i == f // -> 1.0f == 1.0f
Q. 표현범위?
자바에서 int vs float
항목 | int | float |
자료형 크기 | 32bit | 32bit |
표현 범위 | 약 ± 21억 (±2^31) | 약 ± 3.4 * 10^38 (±2^128) |
정밀도(정확도) | 모든 32비트 정수 정확히 표현 | 약 7자리 십진수까지만 정확 |
부동소수점 여부 | X | 소수 가능 (IEEE 754 float) |
자동 형변환 우선순위 | 낮음 | 높음 |
Q. float가 더 넓은 범위를 가지는 이유
- int : 2의 보수로 정수만 정확하게 표현
- float: 소수점을 표현해야 하므로 유효숫자 + 지수부로 구성
Q. 2의 보수와 부동소수점 표현 방식의 차이점? (이건 너무 상식적인 것 같아서 접는글로..)
차이점(메모리적인 측면)
2의 보수로 표현된 정수는 고정된 비트 수로 저장되며, 음수를 나타낼 때는 2의 보수 방식으로 비트가 반전된다. 이 때는 1비트 부호 비트만을 사용하여 값을 부호화한다.
부동소수점은 고정된 비트수를 가지고 유효숫자, 지수부를 따로 나누어 저장한다.
float와 같은 부동소수점 표현 방식과 int와 같은 2의 보수 방식은 기본적으로 서로 다른 목적으로 설계된 데이터 표현 방식이다.
1. 2의 보수
정의
2의 보수는 정수를 표현하는 방식으로, 음수를 처리하는 방법.
메모리 구조
정수는 고정된 비트 크기로 저장된다. 즉, int는 32비트로 저장이 되며, 이 32비트는 양수 및 음수 값들을 표현하는 데 사용된다.
예시
int형의 -5
00000000 00000000 00000000 11111011
2. 부동소수점 표현 방식
정의
실수를 표현하는 방식으로, 정수 부분과 소수점 이핳 값을 표현할 수 있게 설계됨.
구성
유효 숫자(mantissa)와 지수부(exponent), 이진수로 나타냄
IEEE 754 표준을 따른 부동소수점의 메모리 구조
- 유효숫자(mantissa): 숫자의 정확한 값을 저장하는 부분
- 지수부(exponent): 값이 몇 배의 2의 거듭제곱으로 확대되거나 축소되는지를 나타내는 부분
- 부호 비트: 숫자가 양수인지 음수인지를 나타내는 비트
예시
float형의 5.75
- 이진수로 변환: 5.75 -> 101.11
- 정규화: 1/0111 * 2^2로 변환 (소수점 위치를 이동시켜 정규화)
- 지수부와 유효숫자 구성
- 부호비트: 0 (양수)
- 지수부: 2는 127 + 2 = 129로 표현
- 유효숫자: 01110000000000000000000
- 결과적인 32비트 표현
부호 비트 | 지수부 | 유효숫자
0 | 10000001 | 01110000000000000000000
Q. 그렇다면 왜 형변환을 할 때 범위가 큰 것으로 형변환을 하는지?
자동 형변환은 값 손실을 최소화하기 위해 더 넓은 표현 범위를 가진 타입으로 변환됨.
즉, 작은 타입에서 큰 타입으로 형변환을 한다.
Q. 그렇다면.. float, double 형변환을 할 때 double 형이 더 넓은 범위를 가지니 float형이 double형으로 변환이 되는지?
맞음. float는 32비트 부동소수점 타입이고, double은 64비트 부동 소수점 타입이므로 범위가 더 큰 double으로 형변환이 이루어진다.
3. 타입이 다르면 작은 타입을 큰 타입으로 자동 형변환 (Type Casting/Conversion)
이건 위에서 설명한 것과 같다. 즉, 표현 범위가 작은 int를 표현 범위가 큰 float로 형변환을 하게 된다.
(float)i == f // -> 1.0f == 1.0f
4. 형변환된 값들끼리 비교 수행
1.0f == 1.0f
결과
true
추가 자료
Java의 Type Casting에 대한 개요, 예시가 잘 나와있어서 추가로 첨부해본다.
https://labex.io/tutorials/java-how-to-use-type-casting-in-java-division-414176
사소한 것일지 몰라도 깊게 따지고 보면 끝이 없다.
그래도 다시 정리하면서 궁금증이 해소된 것 같아 좋은 것 같음.
'basic' 카테고리의 다른 글
JVM의 메모리 구조 (0) | 2025.05.02 |
---|---|
오브젝트의 이해 (0) | 2025.05.01 |
메모리 아키텍처에 대하여 (폰 노이만 아키텍처, 하버드 아키텍처) (0) | 2025.04.30 |
This is CS50 (4) Algorithms (0) | 2024.06.06 |
This is CS50 (3) Arrays (0) | 2024.06.03 |