문제

C++에서는 min 그리고 max 이상으로 바람직하다 fmin 그리고 fmax?두 정수를 비교하기 위해 기본적으로 동일한 기능을 제공합니까?

이러한 기능 세트 중 하나를 사용하는 경향이 있습니까, 아니면 직접 작성하는 것을 선호합니까(아마도 효율성, 이식성, 유연성 등을 향상시키기 위해)?

노트:

  1. C++ 표준 템플릿 라이브러리(STL)는 다음을 선언합니다. min 그리고 max 표준 C++의 함수 연산 머리글.

  2. C 표준(C99)은 다음을 제공합니다. fmin 그리고 fmax 표준 C의 함수 수학.h 머리글.

미리 감사드립니다!

도움이 되었습니까?

해결책

fmin 그리고 fmax 특히 부동 소수점 번호와 함께 사용하기위한 것입니다 (따라서 "F"). INT에 사용하는 경우 컴파일러/플랫폼에 따라 변환, 기능 호출 오버 헤드 등으로 인해 성능 또는 정밀 손실이 발생할 수 있습니다.

std::min 그리고 std::max 템플릿 함수입니다 (헤더에 정의됩니다 <algorithm>)는 덜 유형의 모든 유형에서 작동합니다 (<) 연산자이므로 이러한 비교를 허용하는 데이터 유형에서 작동 할 수 있습니다. 작업을 원하지 않는 경우 자신의 비교 기능을 제공 할 수도 있습니다. <.

인수가 다른 유형을 가질 때 일치하도록 명시 적으로 변환해야하므로 더 안전합니다. 컴파일러를 사용하면 실수로 64 비트 INT를 64 비트 플로트로 변환 할 수 없습니다. 이러한 이유만으로도 템플릿을 기본 선택으로 만들어야합니다. (Matthieu M & BK1E에 대한 신용)

템플릿이 부유해도 사용하더라도 5월 성능에서 승리하십시오. 소스 코드가 컴파일 장치의 일부이기 때문에 컴파일러는 항상 템플릿 함수로 호출을 내리는 옵션이 있습니다. 때때로 그것은입니다 불가능한 반면에 라이브러리 함수에 대한 호출을 인라인하기 위해 (공유 라이브러리, 링크 시간 최적화의 부재 등).

다른 팁

간에 중요한 차이가 있습니다 std::min, std::max 그리고 fmin 그리고 fmax.

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::min 1-1 대용품이 아닙니다 fmin. 기능 std::min 그리고 std::max 정류가 아닙니다. 두 배로 동일한 결과를 얻으려면 fmin 그리고 fmax 논쟁을 교환해야합니다

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

그러나 내가 말할 수있는 한 이 모든 기능은이 경우 어쨌든 정의 된 구현입니다. 따라서 100% 확신하려면 구현 방법을 테스트해야합니다.


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

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

반면

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

fmax 다음 코드로 에뮬레이션 할 수 있습니다

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::max 서브 세트입니다 fmax.

어셈블리를 살펴보면 Clang이 내장 코드를 사용한다는 것을 보여줍니다. fmax 그리고 fmin 반면 GCC는 수학 라이브러리에서 호출합니다. Clang의 조립 fmax ~와 함께 -O3 ~이다

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

반면 std::max(double, double) 간단합니다

maxsd   xmm0, xmm1

그러나 GCC 및 Clang을 사용하는 경우 -Ofast fmax 간단 해집니다

maxsd   xmm0, xmm1

그래서 이것은 다시 한 번 보여줍니다 std::max 서브 세트입니다 fmax 그리고 느슨한 부동 소수점 모델을 사용할 때 nan 또는 제로에 서명했습니다 fmax 그리고 std::max 동일합니다. 동일한 주장이 분명히 적용됩니다 fmin 그리고 std::min.

FMIN과 FMAX의 전체 지점이 없습니다. 현대 CPU가 플로팅 포인트 Min 및 Max에 대한 고유 (읽기 SSE) 지침을 사용할 수 있도록 C99에 포함되어 테스트 및 가지 (따라서 잘못 예측 된 지점)를 피할 수 있습니다. STD :: MIN 및 STD :: MAX를 사용하여 내부 루프에서 최소 및 최대에 SSE 인트릭스를 사용하여 속도 업이 중요했습니다.

std :: min 및 std :: max는 템플릿입니다. 따라서 플로트, 복식, 긴 복식을 포함하여 연산자보다 적은 유형을 제공하는 다양한 유형에 사용할 수 있습니다. 따라서 일반 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 ++ 상대와 다릅니다.

구현이 64비트 정수 유형을 제공하는 경우 fmin 또는 fmax를 사용하면 다른(잘못된) 대답을 얻을 수 있습니다.64비트 정수는 double로 변환되며, 이는 (적어도 일반적으로) 64비트보다 작은 유효 숫자를 갖습니다.이러한 숫자를 double로 변환하면 최하위 비트 중 일부가 완전히 손실될 수 있습니다.

이는 실제로 다른 두 숫자가 double로 변환되면 결국 동일해질 수 있음을 의미합니다. 결과는 원래 입력 중 하나와 반드시 같지는 않은 잘못된 숫자가 됩니다.

C ++를 사용하는 경우 C ++ Min/Max 함수를 선호합니다. FMIN/FMAX는 모든 것을 플로팅 포인트로오고 나가도록 강요합니다.

또한 C ++ Min/Max 함수는 해당 유형에 대해 연산자를 정의한 한 사용자 정의 유형과 함께 작동합니다.

HTH

당신이 자신을 지적했듯이 fmin 그리고 fmax C99에 도입되었습니다. 표준 C ++ 라이브러리에는 없습니다 fmin 그리고 fmax 기능. C99 표준 라이브러리가 C ++ (지금은)에 통합 될 때까지 이러한 기능의 응용 영역은 깨끗하게 분리됩니다. 당신이 서로를 "선호"해야 할 상황은 없습니다.

템플릿을 사용합니다 std::min/std::max C ++에서, C에서 사용 가능한 모든 것을 사용하십시오.

Richard Corden이 지적한대로 C ++ 함수 MIN 및 MAX를 STD 네임 스페이스로 정의하십시오. 그들은 유형 안전을 제공하고 때로는 바람직하지 않은 혼합 유형 (예 : 플로트 포인트 대 정수)을 비교하지 않도록 도와줍니다.

사용하는 C ++ 라이브러리가 Min/Max를 매크로로 정의한다는 것을 알게되면 충돌을 일으킬 수 있으며, 이런 식으로 Min/Max 기능을 호출하는 원치 않는 매크로 대체를 방지 할 수 있습니다 (추가 브래킷 참조).

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

이것은 효과적으로 비활성화 될 것입니다 인수 종속 조회 (ADL, Koenig Lookup이라고도 불리는 ADL), ADL에 의존하려는 경우.

FMIN 및 FMAX는 플로팅 포인트와 이중 변수에만 해당됩니다.

최소 및 최대는 이진 술어가 주어지면 모든 유형을 비교할 수있는 템플릿 함수입니다. 복잡한 기능을 제공하기 위해 다른 알고리즘과 함께 사용될 수도 있습니다.

사용 std::min 그리고 std::max.

다른 버전이 더 빠르면 구현이 이들에 대해 오버로드를 추가 할 수 있으며 성능과 휴대 성의 이점을 얻을 수 있습니다.

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

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

그건 그렇고,에서 cstdlib 거기 있습니다 __min 그리고 __max 당신이 사용할 수있는.

이상: http://msdn.microsoft.com/zh-cn/library/btkhtd8d.aspx

SSE 지침을 가진 프로세서를 대상으로하는 C ++ 구현은 다음과 같은 전문화를 제공 할 수 없습니다. std :: min 그리고 STD :: MAX 유형 뜨다, 더블, 그리고 긴 더블 동일합니다 fminf, FMIN, 그리고 fminl, 각각?

특수화는 부동 소수점 유형에 대한 더 나은 성능을 제공하는 반면 일반 템플릿은 부동 소수점 유형을 플로팅 포인트 유형으로 강요하지 않고 비 플로이트 포인트 유형을 처리합니다. FMIN모래 fmaxES.

나는 항상 Min 및 Max Macros를 Ints에 사용합니다. 왜 누군가가 정수 값에 FMIN 또는 FMAX를 사용하는지 잘 모르겠습니다.

Min과 Max의 큰 Gotcha는 그들이처럼 보이더라도 기능이 아니라는 것입니다. 당신이 다음과 같은 일을한다면 :

min (10, BigExpensiveFunctionCall())

이 기능 호출은 매크로의 구현에 따라 두 번 호출 될 수 있습니다. 따라서, 내 조직의 모범 사례는 문자 그대로 또는 가변적이지 않은 것들로 Min 또는 Max를 결코 부르지 않는 모범 사례입니다.

fmin 그리고 fmax, 의 fminl 그리고 fmaxl 서명 및 서명되지 않은 정수를 비교할 때 선호 할 수 있습니다. 서명 및 서명되지 않은 숫자의 전체 범위를 활용할 수 있으며 정수 범위와 프로모션에 대해 걱정할 필요가 없습니다.

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

int z = min(x, y);
z = (int)fmin(x, y);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top