C 의 <math.h>
에는 여러가지 수학 함수들이 존재한다.
이들에 관해 간단하게 정리를 해본다.
먼저 간단한 log
함수에 대해 적어본다.
log
는 밑이 e
인 로그 함수이다. 내가 이것을 정리하는 이유는 밑이 x 인 로그를 사용하려면
log(value) / log(x)
라고 적어야 한다.
근데 이것은 로그의 기본적인 공식으로 사용되는 로그 함수의 밑이 무었이든 상관없이 동작한다.
C언어 에서는 log
,log10
즉 자연로그, 상용로그 두가지가 존재한다.
log
함수는 수학함수라 안그래도 속도가 느린데, 밑이 x 인 로그를 구할때 log
, log10
어떤것을 써야 더 빠른가 에대한 의문이 있었다.
결론만 말하면 자연로그인 log
가 상용로그인 log10
보다 두배 가량 빠르다.
역함수가 있는 함수는 삼각함수가 대표적이다.
sin
과 asin
은 Windows 에서 약6배의 차이가 나며 Linux에서는 그정도는 아니지만 확실히 sin
이 빠르다.
이는 cos
과 tan
역시 마찬가지이다.
어떤 수식을 계산해야할때 가능하다면 asin
,acos
,atan
사용은 최소화 하도록 하는게 좋다.
double atan2(double y,double x);
함수의 존재여부도 그러한 이유이다.
atan2
는 y/x 의 atan 값을 반환한다.
#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 가 지원을 하지 않는다.
gcc를 C99, C11로 컴파일 할때 std=c99
, std=c11
로 컴파일하는데 해당 옵션에서는 저 정의가 없다. 근데 저 옵션은 자주 사용하는 옵션이다.
물론 std=gnu99
나 std=gnu11
옵션을 주어 GNUC로 컴파일 하면 된다.
그런데 난 그냥 안쓰고 말련다.
그럼 어떻게 저 값들을 구하는가? (옆에 주석에 써있네)
없는것만 적어보자면
원주율 π 는 acos(-1)
로 사용할 수 있고.
그렇다고 #define PI acos(-1)
과 같은 멍청한 짓은 안하길 바란다.
무리수 e는 exp(1)
로 구할수 있다.
실제로 M_
시리즈는 저렇게 값을 구해 소수점 15자리를 적어놓은것 뿐이다.
몫은 /
이고 나머지는 %
인데.. 같이 구할땐 /%
를 써야할까 div
를 써야할까?
div
함수는 <stdlib.h>
에 정의되어 있으며 원형은 아래와 같다.
typedef struct _div_t{
int quot;
int rem;
} div_t;
div_t div(int number,int denom);
뭐...몫과 나머지를 같이 구해준다. 라는 함수인데 ==더 느리다.==
아무래도 함수 호출 비용때문에 시간이 걸리는거 같다.
조금 시간이 많이 느리니, 사용여부는 각자 알아서 판단하길.
원시 타입에 대해서는 함수 호출하는 경우가 속도가 더 떨어질 수 있다.
제곱의 경우에도 *
을 사용하는게 pow
함수를 쓰는것보다 빠르다.