2009-10-27 10 views
57

C++에서 fminfmax보다 더 바람직하게는 minmax입니까? 두 정수를 비교할 때, 기본적으로 동일한 기능을 제공합니까?C++에서 min 및 max 함수 사용

이러한 기능 집합 중 하나를 사용하는 경향이 있습니까, 아니면 효율성, 휴대 성, 유연성 등을 개선하기 위해 직접 작성하는 경향이 있습니까?

참고 :

  1. C++ 표준 템플릿 라이브러리 (STL)는 표준 C++ algorithm 헤더에 minmax 기능을 선언합니다.

  2. C 표준 (C99)은 표준 C math.h 헤더에 fminfmax 기능을 제공합니다.

미리 감사드립니다.

답변

86

fminfmax은 특히 부동 소수점 숫자 ("f")와 함께 사용됩니다. 정수형으로 사용하면 컴파일러/플랫폼에 따라 변환, 함수 호출 오버 헤드 등으로 인해 성능이나 정밀도 손실이 발생할 수 있습니다.

std::minstd::max는보다 작음 (<) 연산자 모든 유형에서 작동 (헤더 <algorithm> 정의) 템플릿 함수이므로, 그들은 그러한 비교를 할 수있는 데이터 유형에서 동작 할 수있다. <을 사용하지 않으려면 자체 비교 기능을 제공 할 수도 있습니다.

형식이 다른 경우 인수를 명시 적으로 변환해야하므로보다 안전합니다. 컴파일러는 실수로 64 비트 정수를 64 비트 부동 소수점으로 변환 할 수 없습니다. 이 이유만으로도 템플릿을 기본 선택으로해야합니다. (마티유 M & bk1e에 신용)

수레와 템플릿 를 사용하는 경우에도 성능 승리 할 수있다. 컴파일러는 항상 소스 코드가 컴파일 단위의 일부이기 때문에 템플릿 함수에 대한 호출을 인라인하는 옵션을 제공합니다. 때로는 이 불가능합니다.은 라이브러리 함수를 호출하는 반면, (공유 라이브러리, 링크 타임 최적화가없는 등).

+7

경고 : min과 max은 똑같은 유형의 두 변수 만 비교할 수 있습니다. 그래서 int와 double을 비교할 수 없습니다. ( –

+3

True - 최대 (1, 2.0)이 작동하지 않습니다. 최대 (1, 2.0) 또는 최대 (double (1), 2.0)와 같아야합니다. –

+39

어떤 것이 Good Thing ™ IMO입니까? – Cogwheel

0

나는 항상 int에 대해 min 및 max 매크로를 사용합니다. 나는 왜 정수 값에 대해 fmin이나 fmax를 사용해야하는지 잘 모르겠습니다.

min과 max를 가진 큰 잡아 당김은 그들이 그것처럼 보이더라도 기능이 아니라는 것입니다. 당신은 같은 것을 할 경우 :

min (10, BigExpensiveFunctionCall()) 

을 그 함수 호출은 매크로의 구현에 따라 두 번 전화를받을 수 있습니다. 따라서 리터럴 또는 변수가 아닌 것들로 min 또는 max를 호출하지 않는 것이 가장 좋습니다.

+8

std :: min은 매크로가 아닙니다 ... – Cogwheel

+6

min 및 max는 C에서 매크로로 구현되는 경우가 많지만, C++에서는 템플릿으로 구현됩니다. 훨씬 더. –

+3

'#include '이라면 매크로로 정의 된'min'과'max'를 얻을 수 있습니다. 이것은'std :: min'과'std :: max'와 충돌 할 것이기 때문에'#define NOMINMAX'를 사용하여 소스를 컴파일해야합니다. –

4

C++을 사용하는 경우 유형별이기 때문에 C++ 최소/최대 함수를 선호합니다. fmin/fmax는 모든 것이 강제로 부동 소수점으로 변환되도록합니다.

또한 C++ min/max 함수는 해당 형식에 대해 연산자 <을 정의한 경우 사용자 정의 형식에서 작동합니다.

HTH

6

std :: min 및 std :: max는 템플릿입니다. 그래서 그들은 float, double, long double을 포함하여 운영자보다 적은 유형을 제공하는 다양한 유형에서 사용될 수 있습니다. 당신은 일반적인 C++ 코드를 작성하고 싶어한다면, 당신은 같은 것을 할 거라고 : 성능에 관해서는

template<typename T> 
T const& max3(T const& a, T const& b, T const& c) 
{ 
    using std::max; 
    return max(max(a,b),c); // non-qualified max allows ADL 
} 

을, 나는 fmin을 생각하지 않고 fmax는 C++와 다릅니다.

+1

ADL이란 무엇이며, 왜 여기에 ADL이 필요합니까? –

+0

@Rob Kennedy : http : //en.wikipedia.org/wiki/Argument_dependent_name_lookup – bk1e

+1

ADL = 인수 종속 조회. 이 경우에는 자체 max-function과 함께 제공되는 모든 사용자 정의 유형이 특수 연산자보다 작음을 제공하기 때문에 필요하지 않습니다. 이것은 단지 내 습관 일 뿐이며, 주로'swap '과'abs'와 같은 수치 함수를 사용하여 코드를 작성합니다. 특수한 스왑 및 아 bs 기능을 사용할 수 있기를 원할 것입니다. 나는 "네임 스페이스와 인터페이스 원리"에 대한 Herb Sutter의 기사를 읽는 것이 좋습니다. http://www.gotw.ca/publications/mill08.htm – sellibitze

1

fmin 및 fmax는 부동 소수점 및 이중 변수에만 사용됩니다.

min과 max는 바이너리 조건자를 주어진 모든 유형의 비교를 허용하는 템플릿 함수입니다. 또한 다른 알고리즘과 함께 사용하여 복잡한 기능을 제공 할 수 있습니다.

2

자신이 언급 한대로 fminfmax이 C99에 도입되었습니다. 표준 C++ 라이브러리에는 fminfmax 함수가 없습니다. C99 표준 라이브러리가 C++에 통합 될 때까지 (해당되는 경우) 이러한 함수의 응용 프로그램 영역이 완전히 분리됩니다. 하나를 다른 것보다 "선호"해야 할 상황이 없습니다.

당신은 단지 std::min/C++에서 std::max 및 구현 64 비트 정수 타입을 제공하는 경우 C.

6

에서 사용할 수있는 무엇이든 사용, 당신은 FMIN을 사용하여 다른 (잘못된) 답변을 얻을 수 있습니다 템플릿 사용하거나 fmax. 64 비트 정수는 double로 변환되며, 보통 (적어도 보통) 64 비트보다 작은 significand를 갖습니다. 그러한 숫자를 double 값으로 변환 할 때, 최하위 비트 중 일부는 완전히 손실 될 수 있습니다. 그 결과가 잘못된 수있을 것, 즉 반드시 원래의 입력 중 하나 동일하지입니다 -

이 더블로 변환 할 때 동일하게 끝낼 수 있었다 정말 달랐다 두 숫자는 것을 의미한다. 서명 부호없는 정수 비교했을 때

0

fminfmax, fminlfmaxl이 선호 될 수있다 - 당신은 서명과 서명되지 않은 숫자의 전체 범위는 당신이 정수 범위에 대해 걱정하지 않아도된다는 사실을 이용할 수 있으며, 판촉.

unsigned int x = 4000000000; 
int y = -1; 

int z = min(x, y); 
z = (int)fmin(x, y); 
+0

왜 이런 경우를 다루는 전문화가 없습니까? –

1

std::minstd::max 사용. 다른 버전의 빠른 구현이에 대한 과부하를 추가 할 수 있으며 성능과 이동성의 혜택을받을 수 있습니다 다음 경우

: 리처드 Corden는 지적

template <typename T> 
T min (T, T) { 
    // ... default 
} 

inline float min (float f1, float f2) { 
return fmin(f1, f2); 
}  
2

에 정의 된 C++ 함수의 최소 및 최대를 사용 std 네임 스페이스. 그것들은 타입 안전성을 제공하고 때로는 바람직하지 않을 수도있는 혼합 타입 (즉, 부동 소수점 대 정수)을 비교하는 것을 피하는 데 도움을줍니다.

당신은 당신이 사용하는 C++ 라이브러리뿐만 아니라 매크로로 최소/최대를 정의하는 것을 발견하면, 충돌, 당신은 최소/최대 기능이 방법 (통지 여분의 괄호)를 호출 원치 않는 매크로 대체 방지 할 수 있습니다 발생할 수

(std::min)(x, y) 
(std::max)(x, y) 

ADL에 의존하려는 경우에 대비하여 Argument Dependant Lookup (ADL, 또는 Koenig 조회라고도 함)을 사용하지 않도록 설정합니다.

13

fmin과 fmax의 전체 점이 누락되었습니다. 이것은 C99에 포함되어 최신 CPU가 부동 소수점 min 및 max에 대해 원시 (읽기 SSE) 명령어를 사용하고 테스트 및 분기 (따라서 잘못 예측 된 분기)를 피할 수 있습니다. 필자는 std :: min과 std :: max를 사용하여 내부 루프의 최소 및 최대에 SSE 내장 함수를 사용하는 코드를 다시 작성했으며 속도 향상이 중요했습니다.

+1

얼마나 빨라 졌습니까? C++ 컴파일러가 std :: min 을 사용할 때 왜 감지하지 못합니까? –

+4

아마도 그는 테스트 할 때 최적화 기능을 사용하지 않았거나 컴파일러가 '어디서나'실행할 수있는 바이너리를 컴파일하려고 했으므로 SSE를 사용할 수 있는지 여부를 모르고있었습니다. 나는 gcc를 사용하면'-O3 -march = native' 플래그를 전달하면 차이점이 사라질 것이라고 생각합니다. –

+2

C에 포함 된 진짜 이유는 C에 템플릿이나 함수 오버로드가 없기 때문입니다. 부동 소수점 유형에 대해 max보다 단순한 이름 지정된 함수. –

14

.

std::min(-0.0,0.0) = -0.0 
std::max(-0.0,0.0) = -0.0 

fmin(-0.0, 0.0) = -0.0 
fmax(-0.0, 0.0) = 0.0 

반면 그래서 std::minfmin의 1-1 대체하지 않습니다. std::minstd::max 함수는 교환 가능하지 않습니다. 인수
fmin(-0.0, 0.0) = std::min(-0.0, 0.0) 
fmax(-0.0, 0.0) = std::max(0.0, -0.0) 

그러나 지금까지의 내가 all these functions are implementation defined anyway in this case을 말할 수 그래서 당신은 그들이 어떻게 구현되는지 테스트해야 100 % 확신 할 수를 교환해야 fminfmax 하나와 두 배와 같은 결과를 얻을 수 있습니다.


또 다른 중요한 차이점이 있습니다. x ! = NaN 들어 :

std::max(Nan,x) = NaN 
std::max(x,NaN) = x 
std::min(Nan,x) = NaN 
std::min(x,NaN) = x 


fmax

fmax(Nan,x) = x 
fmax(x,NaN) = x 
fmin(Nan,x) = x 
fmin(x,NaN) = x 

하는 반면, 다음 코드

double myfmax(double x, double y) 
{ 
    // z > nan for z != nan is required by C the standard 
    int xnan = isnan(x), ynan = isnan(y); 
    if(xnan || ynan) { 
     if(xnan && !ynan) return y; 
     if(!xnan && ynan) return x; 
     return x; 
    } 
    // +0 > -0 is preferred by C the standard 
    if(x==0 && y==0) { 
     int xs = signbit(x), ys = signbit(y); 
     if(xs && !ys) return y; 
     if(!xs && ys) return x; 
     return x; 
    } 
    return std::max(x,y); 
} 

std::maxfmax의 일부임을 나타낸다 에뮬레이트 될 수있다.

어셈블리를 보면 Clang이 fmaxfmin에 대해 내장 코드를 사용하는 반면 GCC는 수학 라이브러리에서 코드를 호출합니다.-O3fmax 대한 연타의 조립체 std::max(double, double) 것이 -Ofastfmax를 사용 GCC와 연타 들어

maxsd xmm0, xmm1 

그러나 단순히 반면

movapd xmm2, xmm0 
cmpunordsd  xmm2, xmm2 
movapd xmm3, xmm2 
andpd xmm3, xmm1 
maxsd xmm1, xmm0 
andnpd xmm2, xmm1 
orpd xmm2, xmm3 
movapd xmm0, xmm2 

단순히 그래서 방송

maxsd xmm0, xmm1 

진다 다시 std::maxfmax의 하위 집합입니다. 그리고 nan 또는 부호가없는 0이 아닌 더 가벼운 부동 소수점 모델을 사용하면 fmaxstd::max은 동일합니다. 동일한 논거는 분명히 fminstd::min에 적용됩니다.

0

가 C++ 구현 SSE 지침에 프로세서를 대상으로 할 수 없습니다 제공 표준의 전문 ::표준 : 최대 유형 플로트, 더블긴 더블에 대한 최소을하는 fminf, fminfminl의 등가물입니까? 일반 템플릿은 부동 소수점 유형으로 부동 소수점 형식을 강요하기 위해 시도하지 않고 비 부동 소수점 유형을 처리 할 동안

전문 분야는 부동 소수점 유형에 대한 더 나은 성능을 제공 할 것을 FMIN들과 FMAX 방법 예.

+0

인텔 C++은 fdm보다 std :: min의 성능이 좋습니다. gcc에서 fmin의 좋은 성능을 위해서는 한정되지 않은 피연산자를위한 finite-math-only 설정이 필요합니다. – tim18