Nice programing

C ++에서 최소 및 최대 함수 사용

nicepro 2020. 11. 16. 22:09
반응형

C ++에서 최소 및 최대 함수 사용


C에서 ++입니다 minmax바람직 이상 fminfmax? 두 정수를 비교하기 위해 기본적으로 동일한 기능을 제공합니까?

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

메모:

  1. C ++ 표준 템플릿 라이브러리 (STL)는 표준 C ++ 알고리즘 헤더 에서 minmax함수를 선언합니다 .

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

미리 감사드립니다!


fminfmax부동 소수점 수와 함께 사용 (따라서 "F")에 대한 상세이다. int에 사용하면 컴파일러 / 플랫폼에 따라 변환, 함수 호출 오버 헤드 등으로 인해 성능 또는 정밀도 손실이 발생할 수 있습니다.

std::minstd::max(헤더에 정의 된 템플릿 함수이다 <algorithm>보다 작음 (어떤 타입의 작업) <가 이러한 비교를 할 수있는 데이터 유형에서 동작 할 수 있도록) 연산자. 작동하지 않으려면 고유 한 비교 기능을 제공 할 수도 있습니다 <.

유형이 다른 경우 일치하도록 인수를 명시 적으로 변환해야하므로 더 안전합니다. 예를 들어 컴파일러는 실수로 64 비트 int를 64 비트 부동 소수점으로 변환하는 것을 허용하지 않습니다. 이 이유만으로 템플릿을 기본 선택으로 만들어야합니다. (Mathieu M & bk1e에 대한 크레딧)

플로트와 함께 사용하더라도 템플릿의 성능이 향상 될 수 있습니다 . 컴파일러는 소스 코드가 컴파일 단위의 일부이므로 항상 템플릿 함수에 대한 호출을 인라인하는 옵션이 있습니다. 반면에 라이브러리 함수에 대한 호출을 인라인하는 것이 불가능한 경우도 있습니다 (공유 라이브러리, 링크 시간 최적화 부재 등).


중요한 차이가있다 std::min, std::maxfminfmax.

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::minstd::max교환 법칙이 성립하지 않습니다. 와 복식와 같은 결과를 얻으려면 fminfmax하나가 인수를 교환한다

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

그러나 내가 말할 수있는 한 이러한 모든 함수는 어쨌든이 경우에 구현 정의 되어 있으므로 구현 방법을 테스트해야합니다.


또 다른 중요한 차이점이 있습니다. 대상 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.

연타가 코드를 내장 사용하는 어셈블리 쇼에서 찾고 fmaxfminGCC는 수학 라이브러리를 호출하는 반면. fmaxwith에 대한 clang 어셈블리 -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

However, for GCC and Clang using -Ofast fmax becomes simply

maxsd   xmm0, xmm1

So this shows once again that std::max is a subset of fmax and that when you use a looser floating point model which does not have nan or signed zero then fmax and std::max are the same. The same argument obviously applies to fmin and std::min.


You're missing the entire point of fmin and fmax. It was included in C99 so that modern CPUs could use their native (read SSE) instructions for floating point min and max and avoid a test and branch (and thus a possibly mis-predicted branch). I've re-written code that used std::min and std::max to use SSE intrinsics for min and max in inner loops instead and the speed-up was significant.


std::min and std::max are templates. So, they can be used on a variety of types that provide the less than operator, including floats, doubles, long doubles. So, if you wanted to write generic C++ code you'd do something like this:

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
}

As for performance, I don't think fmin and fmax differ from their C++ counterparts.


If your implementation provides a 64-bit integer type, you may get a different (incorrect) answer by using fmin or fmax. Your 64-bit integers will be converted to doubles, which will (at least usually) have a significand that's smaller than 64-bits. When you convert such a number to a double, some of the least significant bits can/will be lost completely.

This means that two numbers that were really different could end up equal when converted to double -- and the result will be that incorrect number, that's not necessarily equal to either of the original inputs.


I would prefer the C++ min/max functions, if you are using C++, because they are type-specific. fmin/fmax will force everything to be converted to/from floating point.

Also, the C++ min/max functions will work with user-defined types as long as you have defined operator< for those types.

HTH


As you noted yourself, fmin and fmax were introduced in C99. Standard C++ library doesn't have fmin and fmax functions. Until C99 standard library gets incorporated into C++ (if ever), the application areas of these functions are cleanly separated. There's no situation where you might have to "prefer" one over the other.

You just use templated std::min/std::max in C++, and use whatever is available in C.


As Richard Corden pointed, use C++ functions min and max defined in std namespace. They provide type safety, and help to avoid comparing mixed types (i.e. float point vs integer) what sometimes may be undesirable.

If you find that C++ library you use defines min/max as macros as well, it may cause conflicts, then you can prevent unwanted macro substitution calling the min/max functions this way (notice extra brackets):

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

Remember, this will effectively disable Argument Dependant Lookup (ADL, also called Koenig lookup), in case you want to rely on ADL.


fmin and fmax are only for floating point and double variables.

min and max are template functions that allow comparison of any types, given a binary predicate. They can also be used with other algorithms to provide complex functionality.


Use std::min and std::max.

If the other versions are faster then your implementation can add overloads for these and you'll get the benefit of performance and portability:

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

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

By the way, in cstdlib there are __min and __max you can use.

For more: http://msdn.microsoft.com/zh-cn/library/btkhtd8d.aspx


Couldn't a C++ implementation targeted for processors with SSE instructions provide specializations of std::min and std::max for types float, double, and long double which do the equivalent of fminf, fmin, and fminl, respectively?

The specializations would provide better performance for floating-point types while the general template would handle non-floating-point types without attempting to coerce floating-point types into floating-point types that way the fmins and fmaxes would.


I always use the min and max macros for ints. I'm not sure why anyone would use fmin or fmax for integer values.

The big gotcha with min and max is that they're not functions, even if they look like them. If you do something like:

min (10, BigExpensiveFunctionCall())

That function call may get called twice depending on the implementation of the macro. As such, its best practice in my org to never call min or max with things that aren't a literal or variable.


fmin and fmax, of fminl and fmaxl could be preferred when comparing signed and unsigned integers - you can take advantage of the fact that the entire range of signed and unsigned numbers and you don't have to worry about integer ranges and promotions.

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

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

참고URL : https://stackoverflow.com/questions/1632145/use-of-min-and-max-functions-in-c

반응형