[C] Math Function

C<math.h> 에는 여러가지 수학 함수들이 존재한다.

이들에 관해 간단하게 정리를 해본다.

1. 자연로그를 쓰자.

먼저 간단한 log 함수에 대해 적어본다.

log는 밑이 e인 로그 함수이다. 내가 이것을 정리하는 이유는 밑이 x 인 로그를 사용하려면

log(value) / log(x) 라고 적어야 한다.

근데 이것은 로그의 기본적인 공식으로 사용되는 로그 함수의 밑이 무었이든 상관없이 동작한다.

C언어 에서는 log,log10 즉 자연로그, 상용로그 두가지가 존재한다.

log 함수는 수학함수라 안그래도 속도가 느린데, 밑이 x 인 로그를 구할때 log , log10 어떤것을 써야 더 빠른가 에대한 의문이 있었다.

결론만 말하면 자연로그인 log가 상용로그인 log10보다 두배 가량 빠르다.

2. 역함수 사용은 최소화

역함수가 있는 함수는 삼각함수가 대표적이다.

sinasinWindows 에서 약6배의 차이가 나며 Linux에서는 그정도는 아니지만 확실히 sin이 빠르다.

이는 costan 역시 마찬가지이다.

어떤 수식을 계산해야할때 가능하다면 asin,acos,atan 사용은 최소화 하도록 하는게 좋다.

double atan2(double y,double x); 함수의 존재여부도 그러한 이유이다.

atan2y/xatan 값을 반환한다.

3. 수학 상수 사용은 글쎄...
#define _USE_MATH_DEFINES
#include<math.h>

위와 같이 _USE_MATH_DEFINES<math.h> 를 포함하기 전에 정의해주면 여러가지 수학 상수들을 사용 할 수 있다.

아니 사실 별거 없다.

무리수 e를 나타내는 M_E

원주율 π를 나타내는 M_PI 등 math.h를 열어보면 자세하게 나와있다.

#define M_E        2.71828182845904523536   // e
#define M_LOG2E    1.44269504088896340736   // log2(e)
#define M_LOG10E   0.434294481903251827651  // log10(e)
#define M_LN2      0.693147180559945309417  // ln(2)
#define M_LN10     2.30258509299404568402   // ln(10)
#define M_PI       3.14159265358979323846   // pi
#define M_PI_2     1.57079632679489661923   // pi/2
#define M_PI_4     0.785398163397448309616  // pi/4
#define M_1_PI     0.318309886183790671538  // 1/pi
#define M_2_PI     0.636619772367581343076  // 2/pi
#define M_2_SQRTPI 1.12837916709551257390   // 2/sqrt(pi)
#define M_SQRT2    1.41421356237309504880   // sqrt(2)
#define M_SQRT1_2  0.707106781186547524401  // 1/sqrt(2)

사실 하나하나 보면 쓸데없다. 왜 저런게 존재하는지 두가지 이유를 추측해보면

  • 예전 C언어에서는 하드웨어의 환경이 그렇게 좋지않고, 속도가 중요하므로 저런것을 계산하지 않겠다.

  • 저런 값을 구하는 법을 모르는 사람들을 위해 있다.

그런데 쓰는데 문제가 없으면, 그냥 쓰겠다.

근데 문제가 있다.....

첫번째 문제는 gcc 가 지원을 하지 않는다.

gccC99, C11로 컴파일 할때 std=c99, std=c11로 컴파일하는데 해당 옵션에서는 저 정의가 없다. 근데 저 옵션은 자주 사용하는 옵션이다.

물론 std=gnu99std=gnu11 옵션을 주어 GNUC로 컴파일 하면 된다.

그런데 난 그냥 안쓰고 말련다.

그럼 어떻게 저 값들을 구하는가? (옆에 주석에 써있네)

없는것만 적어보자면

원주율 π 는 acos(-1)로 사용할 수 있고.

그렇다고 #define PI acos(-1) 과 같은 멍청한 짓은 안하길 바란다.

무리수 e는 exp(1)로 구할수 있다.

실제로 M_ 시리즈는 저렇게 값을 구해 소수점 15자리를 적어놓은것 뿐이다.

4. 연산자 > 함수

몫은 / 이고 나머지는 %인데.. 같이 구할땐 /% 를 써야할까 div를 써야할까?

div 함수는 <stdlib.h> 에 정의되어 있으며 원형은 아래와 같다.

typedef struct _div_t{  
    int quot;
    int rem;
} div_t;
div_t div(int number,int denom);  

뭐...몫과 나머지를 같이 구해준다. 라는 함수인데 더 느리다.

아무래도 함수 호출 비용때문에 시간이 걸리는거 같다.

조금 시간이 많이 느리니, 사용여부는 각자 알아서 판단하길.

원시 타입에 대해서는 함수 호출하는 경우가 속도가 더 떨어질 수 있다.

제곱의 경우에도 *을 사용하는게 pow 함수를 쓰는것보다 빠르다.