부동 소수점 (Float)

부동 소수점은 실수를 (부호) × (가수) × (밑수)^(지수) 형태로 표현하는 방식이다.
‘부동’은 소수점이 움직인다는 의미로, 넓은 범위의 실수를 표현할 수 있다.

특징

  1. IEEE 754 표준을 따름
  2. 부호, 지수, 가수 부분으로 구성

IEEE 754 표준에 따른 부동 소수점 종류

  1. Half Precision
    이 형식은 가장 작은 부동 소수점 표현 방식.
    16비트를 사용한다.

    • 1비트는 부호, 5비트는 지수부, 10비트는 가수부로 구성된다.
      주로 그래픽스나 머신러닝에서 메모리를 절약하기 위해 사용된다.
      약 3자리의 십진 정밀도를 제공하며, ±6.1 × 10⁻⁵에서 ±6.5 × 10⁴까지의 범위를 표현할 수 있다.
      예시:
      Python:
    1
    2
    3
    
    import numpy as np
    x = np.float16(3.14)
    print(x)  # 3.14
    

    JavaScript: JavaScript는 기본적으로 Half Precision을 지원하지 않는다. 외부 라이브러리를 사용해야 한다.

    Java: Java 17부터 Half Precision을 지원합니다.

    1
    2
    3
    
    float f = 3.14f;
    short halfFloat = Float.floatToFloat16(f);
    System.out.println(Float.float16ToFloat(halfFloat));  // 3.140625
    
  2. Single Precision
    가장 일반적으로 사용되는 float 타입.
    32비트를 사용한다.

    • 1비트는 부호, 8비트는 지수부, 23비트는 가수부로 구성된다.
      약 7자리의 십진 정밀도를 제공하며, ±1.18 × 10⁻³⁸에서 ±3.4 × 10³⁸까지의 범위를 표현할 수 있다.
      대부분의 프로그래밍 언어에서 ‘float’ 키워드로 사용된다.
      예시:
      Python:
    1
    2
    3
    
    import numpy as np
    x = np.float32(3.14159265359)
    print(x)  # 3.1415927
    

    JavaScript: JavaScript는 모든 숫자를 64비트로 처리하므로, 32비트 표현은 없다.

    Java:

    1
    2
    
    float f = 3.14159265359f;
    System.out.println(f);  // 3.1415927
    
  3. Double Precision
    더 높은 정밀도가 필요한 경우에 사용되는 형식.
    64비트를 사용한다.

    • 1비트는 부호, 11비트는 지수부, 52비트는 가수부로 구성된다.
      약 15-17자리의 십진 정밀도를 제공하며, ±2.23 × 10⁻³⁰⁸에서 ±1.80 × 10³⁰⁸까지의 범위를 표현할 수 있다.
      대부분의 언어에서 ‘double’ 키워드로 사용된다.
      예시:
      Python:
    1
    2
    
    x = 3.14159265359
    print(x)  # 3.14159265359
    

    JavaScript:

    1
    2
    
    let x = 3.14159265359;
    console.log(x);  // 3.14159265359
    

    Java:

    1
    2
    
    double d = 3.14159265359;
    System.out.println(d);  // 3.14159265359
    
  4. Quadruple Precision
    매우 높은 정밀도가 필요한 과학적 계산이나 금융 계산에서 사용된다.
    128비트를 사용한다.

    • 1비트는 부호, 15비트는 지수부, 112비트는 가수부로 구성된다.
      약 34자리의 십진 정밀도를 제공하며, ±6.5 × 10⁻⁴⁹⁶⁶에서 ±6.5 × 10⁴⁹⁶⁶까지의 엄청난 범위를 표현할 수 있다.
      예시:
      Python, JavaScript, Java 모두 기본적으로 128비트 부동 소수점을 지원하지 않는다. 특별한 라이브러리나 클래스를 사용해야 한다.
      Java에서는 BigDecimal 클래스를 사용하여 높은 정밀도를 구현할 수 있다:
    1
    2
    3
    4
    
    import java.math.BigDecimal;
    
    BigDecimal bd = new BigDecimal("3.14159265358979323846264338327950288419716939937510");
    System.out.println(bd.toPlainString());
    

Half Precision이 Single Precision보다 더 효율적인 이유

  1. 메모리 사용량 감소: Half Precision은 16비트를 사용하는 반면, Single Precision은 32비트를 사용한다. 이로 인해 메모리 사용량이 절반으로 줄어들어 더 큰 모델이나 더 큰 미니배치를 학습할 수 있다.
  2. 메모리 대역폭 향상: 더 적은 비트를 사용하므로 데이터 전송 시간이 단축된다.
  3. 연산 속도 향상: NVIDIA GPU의 경우 Half Precision 연산이 Single Precision에 비해 최대 8배 빠른 처리량을 제공한다.
  4. 에너지 효율성: 더 적은 비트를 사용하므로 연산에 필요한 에너지가 감소한다.
  5. GPU 성능 최적화: 최신 GPU는 Half Precision 연산에 최적화되어 있어, 특히 딥러닝 워크로드에서 성능 향상을 제공한다.
  6. 캐시 효율성: Half Precision 값은 더 작은 메모리 공간을 차지하므로, 프로세서의 캐시에 더 많은 데이터를 저장할 수 있다. 하지만 Half Precision은 정밀도가 낮아 모든 상황에 적합하지는 않다. 따라서 많은 경우 Mixed Precision 기법을 사용하여 정확도를 유지하면서 성능을 향상시킨다.

특성

  1. 넓은 범위의 실수 표현 가능
  2. 정확한 값이 아닌 근사값 표현
  3. 연산 시 오차 발생 가능

연산 종류 및 설명

  1. 사칙연산: 덧셈, 뺄셈, 곱셈, 나눗셈
  2. 비교연산: 대소 비교
  3. 형변환: 정수형이나 문자열로 변환

부동 소수점 사용 시 주의사항

  1. 정밀도 문제: 이진 부동소수점으로 인해 일부 십진수는 정확히 표현할 수 없다.
  2. 비교 연산: 직접적인 등호 비교 대신 허용 오차를 사용해야 한다.
  3. 금융 계산: 정확한 계산이 필요한 경우 Decimal 같은 정밀 산술 타입을 사용해야 한다.

참고 및 출처