Lv 0. 유한소수 판별하기. *다시 풀어보기*

https://school.programmers.co.kr/learn/courses/30/lessons/120878

 

#include <string>
#include <vector>
#include <numeric>

using namespace std;

int solution(int a, int b) {
    //최대공약수를 이용해서 b를 나누고, b의 소인수가 2와 5만 있는지 확인하면 될듯
    int t=gcd(a,b);
    int chk=b/t;
    
    while(chk%2==0 || chk%5==0){
        if(chk%2==0) chk/=2;
        if(chk%5==0) chk/=5;
    }
    if(chk==1) return 1;
    return 2;
}

처음에 gcd() 함수를 이용해서 해결하기 위해, gcd() 함수가 어떤 헤더에 있는지 기억이 나지 않아서 bits/stdc++.h 형태로 모두 포함시켜서 문제를 해결했다. 

그리고 나서 어느 헤더에 있을지, algorithm인가, cmath인가, 뭐 math.h 인가 등등, 직접 포함시켜보며 찾아보려 했는데, 찾지 못해서 프로그래머스에서 제공해주는 c++ 레퍼런스 사이트에서 gcd 를 검색해서 해당 함수가 numeric 헤더에 포함되어 있음을 확인하였다(c++17부터)

 

https://devdocs.programmers.co.kr/cpp/numeric/gcd

 

DevDocs

 

devdocs.programmers.co.kr

 

이때에, 내가 지속적으로 떠올린 cmath와의 차이점에 대해서 궁금해서 지피티 검색 해보았고 내용을 첨부한다. 

C++ 표준 라이브러리에서 `numeric` 헤더는 수치 연산과 관련된 몇 가지 유용한 함수 및 클래스를 제공하는 헤더 파일입니다. 이 헤더는 주로 수학 계산이나 수치 해석과 같은 수치 연산 작업을 수행할 때 사용됩니다.

`numeric` 헤더의 주요 요소와 `cmath` 헤더와의 차이점은 다음과 같습니다:

1. **수학 함수와 관련성:**
   - `cmath` 헤더는 수학 함수와 관련된 다양한 수학 연산 함수를 제공합니다. 이러한 함수는 삼각 함수, 지수 함수, 로그 함수, 제곱근 함수 등을 포함합니다.
   - `numeric` 헤더는 수학 함수보다는 수치 연산과 관련된 함수를 중심으로 제공합니다. 이 헤더는 수치 미적분, 수치 통계, 수치 루틴 등과 관련된 함수를 포함합니다.

2. **포함된 함수와 클래스:**
   - `numeric` 헤더에는 수치 적분을 수행하는 `integrate` 함수와 수치 적분 결과를 저장하는 `integral` 클래스와 같은 수치 연산을 위한 특수한 함수와 클래스가 포함되어 있습니다.
   - `cmath` 헤더에는 표준 수학 함수 (예: `sin`, `cos`, `exp`, `log` 등)와 관련된 함수가 포함되어 있습니다.

3. **용도 및 사용 사례:**
   - `cmath` 헤더는 주로 수학적 계산에 사용됩니다. 삼각 함수, 로그 함수, 지수 함수와 같은 수학적 계산을 수행할 때 유용합니다.
   - `numeric` 헤더는 수치 미분, 적분, 수치 해석, 수치 루틴 등과 같은 수치 계산 및 과학 및 엔지니어링 응용 프로그램에 사용됩니다.

간단히 말해서, `cmath` 헤더는 일반적인 수학 함수를 제공하고, `numeric` 헤더는 수치 계산과 관련된 특수한 함수와 클래스를 제공합니다. 선택한 작업에 따라 이 두 헤더를 적절히 사용할 수 있습니다.

 

++++++++++++
추가적으로 이제 다른 사람의 풀이를 보고, 그중에서 배울만한 부분이 있는 풀이를 첨부할 것인데, 나같은 경우 위의 풀이에서 결국 실질적으로 수를 약분하듯이, 먼저 gcd 를 구해서 수를 나누고, 그 나눈 수를 다시 2 또는 5로 계속 나누어서 2또는 5 외의 다른 수가 있는지를 통해서 판별하는 형태였는데, 다른 사람의 풀이를 보니까 아주 깔끔하고 간결하게, 그리고 짧게 , 그리고 gcd() 를 찾을 필요 없이 푸는 풀이가 있어서 첨부한다.

 이 풀이의 경우는 결국에는 b를 2와 5로 계속 나누어 가다가, 더이상 나누어지지 않을때, 그 수로 a 를 나누었을때, 그때에 b에 2와 5를 제외한 불필요한 원소가 있는 경우 나머지가 0이 아니게 되고, 만약 0이면 유한소수, 아니라면 무한소수 라는 판단을 하는 코드이다. 

#include <string>
#include <vector>
#include <iostream>

using namespace std;

int solution(int a, int b)
{
    int answer=0;

    while(b%2==0) b/=2;
    while(b%5==0) b/=5;
    answer=a%b==0?1:2;

    return answer;
}

나같은 경우 최종값이 1이냐 아니냐로 판단하는데, 이 경우 2와 5로 지속적으로 b를 나누어서 나온 수가, 결국 gcd 여서 a%b 의 값이 0이 되어야지만 유한소수다 라는 성질을 이용한 풀이이다. 

아주 좋은 풀이라고 생각된다. 내가 필요하다고 생각한 연산을 수행하지 않았다. 왜냐면 결국 필요한건 그 연산이 아니라 저 두 수의 관계일 뿐이니까.

아주 멋진 풀이이다. 이건 기억해두고 다음에 한번 이렇게 역방향으로 생각해보도록 하자. 말 그대로 a/b를 해서 약분을 하고.. 등등으로 순차적으로 문제를 해결할 필요가 없다. 조금 더 현명하게 멀리까지 생각해보자. 

 

 

 

  Comments,     Trackbacks