코딩 테스트

[코딩테스트 2일차] BAEKJOON 1008번 : A/B

sunlight-dby 2025. 4. 2. 01:45

[BAEKJOON 1008번 : A / B]

 

[고찰]

이 문제는 부동 소수점에 대해 잘 알고 있어야 하는 문제입니다.

간단히 printf("%.9f", a/b)로 풀었는데, 이 문제에 대해 검색을 해보니 C++에서 소수점을 표현하는 방법이 따로 존재한다는 것을 알게되었습니다.

그래서 부동소수점의 개념과 C 스타일, C++ 스타일로 모두 푸는 방법을 정리하려고 합니다.

 

[개념]

실수는 예제 출력에서처럼 0.33333333333⋯ 과 같이 무한 소수가 존재합니다.

하지만, 컴퓨터 상에서는 이런 무한 소수를 정확하게 표기를 하는데 한계가 있기 때문에, 컴퓨터 상에서 근사하여 표현할 때 소수점의 위치를 고정하지 않고 그 위치를 나타내는 수를 따로 적는 방법을 통해 이를 해결합니다.

 

부동 소수점은 아래의 그림과 같이 표현됩니다.

 

https://ko.wikipedia.org/wiki/부동소수점

 

 - 32비트 컴퓨터에서의 부동 소수점 방식

  • 부호부 (1bit) : 양수일 때는 0, 음수일 때는 1
  • 지수부 (8bit) : 부호가 없는 정수
    • 지수부는 정규화 과정인 실수를 비트로 표현한 뒤, 소수점을 가장 앞으로 만들 때 필요한 2의 승수를 말합니다.
  • 정규화된 가수부 (23bit)
    • 부호가 없는 정수며, 소수점 아래 수들을 의미합니다.
    • 가수부의 가장 앞의 비트는 정규화되었으므로 1이 됩니다.

 

[정리]

이렇듯 컴퓨터 상에서 최대한 근사하게 표현하기 위해 '부동 소수점' 방식을 활용하지만, 아무래도 근사값을 표현하는 것이기에, 실제 값과는 오차가 발생할 수 밖에 없는 것입니다.

 

정밀도에 의존하는 실수 표현에서, 근사값과 실제값의 차이를 줄이기 위해서는 최대한 많은 비트를 쓸 수 있는 자료형을 선택해야 합니다.

 

실수 자료형은 float과 double, long double이 있는데, 해당 문제에서는 오차가 10⁻⁹ 이하여야 합니다.

 

※ double과 long double

vs의 환경에서는 두 자료형 모두 8byte의 크기를 가집니다.

하지만, gcc, g++의 환경에서는 16byte의 크기를 가진다는 것을 참고해두면 좋을 것 같습니다.


형식 유효 자릿수 바이트 수
float 6 - 7 4
double 15 - 16 8

 

위의 표는 'Learn Microsoft'의 float 형식에 대해 설명해주는 페이지에서 가져온 자료입니다.

 

실제로 해당 문제를 float 자료형을 사용하면 틀렸다는 결과를 받게 됩니다.

 

 

[C style solution]

#include <stdio.h>

int main(void)
{
    double a;
    double b;
    
    scanf("%lf %lf", &a, &b);
    
    printf("%.9lf", a / b);
    
    return 0;
}

 

그럼 위의 코드와 같이 double 자료형을 사용하여 풀면 됩니다.

 

※ 출력할 때는 %f로 출력하여도 되지만, 입력 받을 때는 %f로 받으면 float형으로 읽어들이게 된다.

 


 

이번에는 C++에서 소수점 자리를 표현하는 방법에 대해서 알아보려고 합니다.

 

[개념]

  • std::cout.precision(n)
    • cout.precision(n)은 실수를 n자리 만큼만 출력하게 됩니다.
  •  std::fixed
    • fixed는 고정 소수점 표기로, fixed를 사용한 후로는 cout.precision(n)에서 받은 n값만큼 소수점 아래 자리 수를 출력해줍니다.
    • fixed를 해제하기 위해서는 std::cout.unsetf(std::ios::fixed)를 이용하면 됩니다.
  • std::setprecision(n)
    • <iomanip> 헤더 파일에 정의되어 있으며, n값만큼 반올림하여 출력해줍니다.

[<iomanip> style solution]

#include <iostream>
#include <iomanip>

int main(void)
{
    double a, b;
    
    std::cin >> a >> b;
    
    std::cout << std::fixed;
    std::cout << std::setprecision(9) << a / b << std::endl;
    
    return 0;
}

 

 

[C++ style solution]

#include <iostream>

using namespace std;

int main(void)
{
    double a, b;
    cin >> a >> b;
    
    cout.precision(9);
    cout << fixed;
    
    cout << a / b;
    
    return 0;
}