java

[Java] Int 와 long / float 와 double

Across 2023. 4. 3. 20:26

Int 와 float 로 지정 되는 변수는 32bit 

long 과 double로 지정 되는 변수는 64bit로 표현된다.

 

이때, 자바에서는 long 으로 지정될 때 수치 끝에 l or L을

float로 표현 될 때는 f or F 붙여야만 오류가 나지 않는다.

왜일까 ?

 

우선 int 와 long 의 표현범위 차이를 보자

int 의 표현 범위는 -2,147,483,648~ 2,147,483,647

long의 표현 범위는 -9,223,372,036,854,775,808~ 9,223,372,036,854,775,807

 

        long a = 21474836471;

이경우에

이런 오류를 마주 할 수 있다 .

long의 경우 우선적으로 4byte인 intger로 메모리 절약 차원에서 저장되게되는데 

적당한 양의 수를 커버 할 수 있고 JVM에서 피연산자를 4byte단위로 저장하게 되기 때문이다.

        long a = 21474836471L;

인경우에 정상적으로 저장되는 걸 알수 있다.

 

그런데 4byte단위가 유리하고 메모리 절약을위해 상대적으로 작은 int를 기본으로 선택한 정수는 이해가 되는데

실수의 경우 더 큰 double 이 기본인게 이해가 안 됐다.

float a = 1.1;

double로 기본 저장됨을 알 수 있다.

0.1 0.2 같은 특정 소수는 이진법으로 변환하면 무한히 순환하게 되는데 가능한 근사치로 

IEEE 754에 따라 저장하는데, 이때 생기는 오차를 줄이려고 기본적으로 double로 사용한다.

        float a = 0.1f;
        double b = 0.1;
        System.out.println(a+0.2);
        System.out.println(b+0.2);

이경우 float 에 욱여넣은 대가를 받게 되는데 

어마무시한 오차를 마주할 수 있게된다.

 

모든 소수가 그런 건 아니고 0.125 0.25 같은 류는 별 문제가 없는데 (1/8 , 1/4 등등)

분모가 2의 배수인경우는 근사치가 아니라 그냥 표현이 되기 때문이다.

        float a = 0.125f;
        double b = 0.0625;
        System.out.println(a+0.125);
        System.out.println(b+1.25);

이런 소수점을 사용하면 당연히 정확도 면에서 문제가 생기게 되는데

단위를 줄여서 사용 (ex) 0.1 달러 => 10센트)  하거나

java에서 지원하는 BigDecimal 함수를 사용한다거나 하는 해법이 있기는 하다.

https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/math/BigDecimal.html

 

BigDecimal (Java SE 15 & JDK 15)

All Implemented Interfaces: Serializable, Comparable public class BigDecimal extends Number implements Comparable Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit int

docs.oracle.com

예시로 합을하나 해보면

import java.math.BigDecimal;
public class Main {
    public static void main(String[] args) {
        BigDecimal value1 = new BigDecimal("0.1");
        BigDecimal value2 = new BigDecimal("0.2");
        System.out.println(value1.add(value2));
    }
}

정확한 결과를 얻을 수 있다.

소수의 사용을 지양하는 방법이 가장 좋은것 같긴하다.