반응형

cpp numerics library

수치 라이브러리


일반 수학 함수들은 <cmath> 헤더에 선언되어 있고 std::sin, std::sqrt 등으로 사용할 수 있다. 네임스페이스는 std를 사용.

복소수는 <complex> 헤더, 알고리즘은 <numeric> 헤더를 사용한다.


++Common mathematical functions

+abs(value)    ; 절대값. 데이터 타입은 int, long, long long, float을 지원한다.

타입을 명시한 함수도 있다. fabs(float), labs(long) , llabs(long long) (C++11)


+div(x, y)    ; 몫과 나머지를 구한다.

std::div_t div(int x, int y) ; 데이터 타입은 long, long long도 지원. ldiv(), lldiv() 사용.

struct div_t { int quot; int rem; }    ; 리턴값인 div_t 타입은 몫과 나머지 필드가 있다.

itoa 함수 구현 예제

std::string itoa(int n, int base) {

   std::string buf ;

   std::div_t dv{} ; 

   dv.quot = n ;

   do {

      dv = std::div(dv.quot, base) ;

      buf += "0123456789abcdef"[std::abs(dv.rem)] ;

   } while (dv.quot) ;

   if (n<0) buf +='-' ;

   return { buf.rbegin(), buf.rend() } ;

}


+큰값, 작은값

max(a,b), fmax(a,b) 등. max는 int, long, long long, fmax는 float, double, long double

min(a,b), fmin(a,b) 등


+오차

fdim(a,b) ; a-b 값이 0보다 크면 a-b값을 리턴. 그렇지 않으면 0리턴. (dim 은 없다. fdim 사용 )


+지수, 로그

exp(arg)    ; 자연상수 e의 arg승수 값. e^arg.  타입은 float, double, long double

exp2(arg)    ; 2^arg  (C++11)

log (arg)   ;   ln(arg) 자연로그

log10(arg)  ; 밑이 10인 로그

pow(x, y)    ; x^y 

sqrt(x)    ; root(x)


+삼각함수

sin, cos, tan, asin, acos, atan

const double pi = std::acos(-1) ;

std::sin( pi/6 )    --> 0.5

std::sin( pi/2 )    --> 1

2 * std::atan( INFINITY )    --> 3.14159 (pi)


atan2(y, x)    ; atan ( y/x ),  -pi~pi 범위의 리턴값


hyperbolic 삼각함수 ; sinh, cosh, tanh, asinh, acosh, atanh 

sinh(arg) ;   ( e^arg - e^-arg ) / 2

cosh(arg) ;  ( e^arg + e^-arg ) / 2

tanh(arg) ;  sinh / cosh


+ 가까운 정수

ceil ; 올림

floor ; 내림

round ; 반올림 (C++11)

float round(float arg) ; double round (double arg) ; ... long double 등.











'Develop > C&CPP' 카테고리의 다른 글

libcurl HTTP POST send 모듈/curl 커맨드 방식도 지원  (0) 2018.07.13
if or 비교시 어떤 식의 성공으로 진입했는지 구분  (0) 2018.07.13
Preprocessor  (0) 2018.06.20
deque  (0) 2018.06.13
stack / queue  (0) 2018.06.12
반응형

cpp preprocessor (전처리기)


전처리기는 소스코드를 컴파일 전단계 (translation phase)에서 처리된다. (런타임이 아니다.) 전처리가 된 후 컴파일러로 전달된다.


+지시어

#으로 시작한다.

키워드로는 define, undef, include, if, ifdef, ifndef, else, elif, endif, line, error, pragma 가 있다.

null 지시어로 #만 쓰는 것도 가능하다. (아무일도 안 함.)


+기능

전처리기는 소스 파일의 번역을 한다.

소스의 일부를 조건에 따라 컴파일할 수 있다. (#if, #ifdef, #ifndef, #else, #elif, #endif)

텍스트를 변경하는 매크로 기능을 한다. (텍스트를 붙이거나 식별자를 스트링으로 사용하는 등) (#define, #undef,  오퍼레이터로써 # , ## )

다른 파일들을 포함시킬 수 있다. (#include)

에러를 발생시킬 수 있다. (#error)

파일명과 라인 번호 정보를 알 수 있다. ( #line )

지정된 방식으로 작업을 한다. (#pragma)


+조건적 포함

#if [expression]

#ifdef [identifier]

#ifndef [identifier]

#elif [expression]

#else

#endif

조건에 따라 코드 블록이 수행된다.


#if, #elif 뒤에 나오는 expression은 상수적 표현을 의미한다. unary 연산자를 포함할 수 있고,  defined identifier 나  defined (identifier) 를 사용할 수 있다. 

expression의 값이 non-zero이면 해당 블록이 처리되고, 0이면 스킵된다.


#ifdef, #ifndef는 다음과 같다. (identifer가 매크로명으로 정의되었는지 검사한다.)

#if defined identifier

#if !defined identifier


#define ABCD 2

#include <iostream>

int main()

{

#ifdef ABCD

std::cout << "1: yes\n" ;

#else

std::cout << "1:no\n" ;

#endif


#ifndef ABCD

std::cout << "2:no1\n" ;

#elif ABCD==2

std::cout << "2.yes\n" ;

#else

std::cout << "2.no2\n" ;

#endif


#if !defined(DCCA) && (ABCD < 2*4-3)

std::cout << "3. yes\n" ;

#endif

}

모두 yes가 출력됨.



+텍스트 변경 매크로

#define identifier    replacement-list

#define identifier(parameters)    replacement-list

#define identifier(parameters, ...)    replacement-list    (C++11)

#define identifier(...)    replacement-list (C++11)

#undef identifier


#define은 지정한 식별자를 replacement-list로 변경해 준다.

객체같은 매크로 ; identifier를 replacement-list로 교체한다.

함수같은 매크로 ; 위와 같지만 추가적으로 파라미터를 사용한다.

variable arguments의 경우 __VA_ARGS__ identifier를 사용한다. 

__VA_OPT__(content)는 __VA_ARGS__가 비어 있지 않을 경우 확장된다.

#define F(...)  f(0 __VA_OPT__(,) __VA_ARGS__)

F(1,2,3) --> f(0, 1,2,3)

F()    --> f(0)


#define G(X, ...)    f(0, X __VA_OPT__(,) __VA_ARGS__ )

G(a,b,c) --> f(0, a,b,c)

G(a,) --> f(0, a)

G(a) --> f(0, a)


#define SDEF(sname, ...)    S sname __VA_OPT__(= {__VA_ARGS__} )

SDEF(foo);    --> S foo;

SDEF(x, 1,2,3);    -->  S x = {1,2,3};



오퍼레이터 #, ##

함수같은 매크로에서 replacement-list 내부에서 식별자 앞에 # 오퍼레이터를 붙이면 결과를 ""로 묶게 된다. 내부에 "가 있으면 \도 자동으로 추가된다.

 

#define showlist(...)    puts(#__VA_ARGS__)

showlist() ;     -->  puts("") ;

showlist(1,"x", int);     --> puts("1, \"x\", int") ;


repplacement-list 내부에 연속된 두 개의 식별자 사이에 ## 오펴레이터가 추가되면 파라미터들을 두 식별자로 바꾸게 된다. 이 작업은 스트링을 붙여서 인식하게 된다.

#define Func(x) Func ##x

Func(1)    --> Func1 

Func(2)    --> Func2



#include <iostream>


#define FUNC(name, val) int FUNC_##name() {  return val ; }

FUNC(aaa, 10)

FUNC(bbb, 20)

FUNC(ccc, 30)

int main() {

    std::cout << FUNC_aaa()  << std::endl ;

    std::cout << FUNC_bbb()  << std::endl ;

    std::cout << FUNC_ccc()  << std::endl ;

return 0 ;

}

10, 20, 30이 출력된다.

FUNC(aaa, 10)   -->   int FUNC_aaa() { return 10 ; } 

위와 같이 풀린다.


+ Predefined macro

__FILE__    ; 현재 소스 파일명으로 확장 (string)

__LINE__    ; 현재 라인 번호 (int)

__DATE__    ; 컴파일 날짜(translation date)  "Mmm dd yyyy"

__TIME__    ; 컴파일 시간 "hh:mm:ss"


  • 소스 파일 포함 ; include

#include <filename>

#include "filename"

해당 파일을 그 위치에 포함시킨다.

C, C++ 라이브러리는 표준 include디렉터리에서 불러들인다. (include 디렉터리는 컴파일 옵션으로 설정할 수 있다.) 

""로 지정하면 소스파일의 디렉터리에서 검색한다. 못찾으면 표준 include 디렉터리에서 찾는다.

nested된 include에 의해 반복될 경우를 막기위해 다음과 같이 한 번한 include되게 한다.

#ifndef _FOO_H_

#define _FOO_H_

// to do..

#endif

pragma를 지원하는 컴파일러에서 아래와 같이 사용하면 위 효과를 동일하게 할 수 있다.

#pragma once


  • 에러 지시

#error error_message

위 지시자를 만나면 에러 메시지를 출력한다.  컴파일 시점에서 발생한다.

#if !WINDOWS_XP && !WINDOWS_7

#error Please check your OS

#endif


  • 파일명과 줄번호 정보

#line lineno

#line lineno "filename"

다음 줄 라인 번호를 lineno로 변경한다. 매크로 __LINE__ 값이 바뀐다.

뒤에 파일명을 주면 __FILE__ 매크로인 파일명이 바뀐다.


#line 777 "test.cc"

assert(2+2==5) ;

위 소스를 컴파일 할 경우, test.cc:777 에서 assertion 에러가 발생한다.



'Develop > C&CPP' 카테고리의 다른 글

if or 비교시 어떤 식의 성공으로 진입했는지 구분  (0) 2018.07.13
Numerics library  (0) 2018.06.21
deque  (0) 2018.06.13
stack / queue  (0) 2018.06.12
cstring  (0) 2018.06.11
반응형

cpp deque

include <deque>

double ended queue . 입출구가 양쪽 끝에 달린 형태.


++Iterators

begin, end, rbegin, rend, cbegin, cend, crbegin, crend


++capacity

size, max_size, resize, empty, shrink_to_fit


++elements access

[], at, front, back


++modifiers

assign, push_back, push_front, pop_back, pop_front

insert, erase, swap, clear, emplace, emplace_front, emplace_back


ex)

std::deque<int> myq (2, 100) ;    // 100을 값으로 2개 노드 생성..  100,100

myq.push_front(200) ;    // 200,100,100

myq.push_front(300) ;    // 300,200,100,100

myq.push_back(99) ;    // 300, 200,100,100, 99

std::cout << myq.front() << '\n' ;    // 300

std::cout << myq.back() << '\n' ;  // 99

myq.pop_front() ;     // 200,100,100,99

myq.pop_back() ;    // 200,100,100

// 출력

for (std::deque<int>::iterator it=myq.begin(); it!=myq.end(); ++it) {

  std::cout<<' ' << *it ;

}


+insert

iterator insert(const_iterator pos, const value_type& val) ;    // 지정된 위치에 삽입.

iterator insert( ", size_type n, const vlaue_type &val) ;    // 지정된 위치에 해당 값을 n개 삽입. (fill)

iterator insert(", InputIterator first, last) ;    // 지정한 위치에 범위를 삽입.

iterator insert(", initializer_list<value_type> il) ;

리턴값은 새로 추가된 첫번째 엘리먼트의 위치


std::deque<int> myq ;

for (int i=1; i<6; i++) myq.push_back(i);    // 1 2 3 4 5

std::deque<int>::iterator it = myq.begin() ; // it point 1

++it ;    // next position ; it point 2

it = myq.insert(it, 10) ;        // 1 10 2 3 4 5

myq.insert(it, 2, 20);    // 1 20 20 10 2 3 4 5

+erase

지정된 위치 또는 범위를 삭제.

리턴값은 삭제된 범위에 처음 오게 될 요소의 위치.

myq.erase( myq.begin()+3) ;

myq.erase( myq.begin(), myq.begin()+3) ;




'Develop > C&CPP' 카테고리의 다른 글

Numerics library  (0) 2018.06.21
Preprocessor  (0) 2018.06.20
stack / queue  (0) 2018.06.12
cstring  (0) 2018.06.11
thread mutex  (0) 2018.06.10

+ Recent posts