在 C++ 中使用 min 和 max 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1632145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:39:50  来源:igfitidea点击:

Use of min and max functions in C++

c++cmaxmin

提问by bporter

From C++, are minand maxpreferable over fminand fmax? For comparing two integers, do they provide basically the same functionality?

从 C++ 来看,是min并且maxfmin和更可取fmax吗?对于比较两个整数,它们是否提供基本相同的功能?

Do you tend to use one of these sets of functions or do you prefer to write your own (perhaps to improve efficiency, portability, flexibility, etc.)?

您倾向于使用这些函数集之一还是更喜欢编写自己的函数(也许是为了提高效率、可移植性、灵活性等)?

Notes:

笔记:

  1. The C++ Standard Template Library (STL) declares the minand maxfunctions in the standard C++ algorithmheader.

  2. The C standard (C99) provides the fminand fmaxfunction in the standard C math.hheader.

  1. C++ 标准模板库 (STL)在标准 C++算法头文件中声明minmax函数。

  2. C 标准 (C99)在标准 C math.h头文件中提供fminfmax函数。

Thanks in advance!

提前致谢!

回答by Cogwheel

fminand fmaxare specifically for use with floating point numbers (hence the "f"). If you use it for ints, you may suffer performance or precision losses due to conversion, function call overhead, etc. depending on your compiler/platform.

fmin并且fmax专门用于浮点数(因此是“f”)。如果您将它用于整数,您可能会因转换、函数调用开销等而遭受性能或精度损失,具体取决于您的编译器/平台。

std::minand std::maxare template functions (defined in header <algorithm>) which work on any type with a less-than (<) operator, so they can operate on any data type that allows such a comparison. You can also provide your own comparison function if you don't want it to work off <.

std::minstd::max是模板函数(在 header 中定义),它们可以使用<algorithm>小于 ( <) 运算符处理任何类型,因此它们可以对允许进行此类比较的任何数据类型进行操作。如果您不希望它工作,您也可以提供自己的比较功能<

This is safer since you have to explicitly convert arguments to match when they have different types. The compiler won't let you accidentally convert a 64-bit int into a 64-bit float, for example. This reason alone should make the templates your default choice. (Credit to Matthieu M & bk1e)

这更安全,因为当参数具有不同类型时,您必须显式转换参数以匹配。例如,编译器不会让您意外地将 64 位 int 转换为 64 位浮点数。仅此原因就应该使模板成为您的默认选择。(归功于 Matthieu M & bk1e)

Even when used with floats the template maywin in performance. A compiler always has the option of inlining calls to template functions since the source code is part of the compilation unit. Sometimes it's impossibleto inline a call to a library function, on the other hand (shared libraries, absence of link-time optimization, etc.).

即使与浮动一起使用,模板也可能在性能上获胜。编译器始终可以选择内联对模板函数的调用,因为源代码是编译单元的一部分。另一方面,有时不可能内联对库函数的调用(共享库、缺少链接时优化等)。

回答by Z boson

There is an important difference between std::min, std::maxand fminand fmax.

有一个重要区别std::minstd::maxfminfmax

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

whereas

然而

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

So std::minis not a 1-1 substitute for fmin. The functions std::minand std::maxare not commutative. To get the same result with doubles with fminand fmaxone should swap the arguments

所以std::min不是 1-1 的替代品fmin。函数std::minstd::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)

But as far as I can tell all these functions are implementation defined anyway in this caseso to be 100% sure you have to test how they are implemented.

但据我所知,在这种情况下所有这些函数都是实现定义的,因此要 100% 确定您必须测试它们是如何实现的。



There is another important difference. For x ! = NaN:

还有一个重要的区别。对于x ! = NaN

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

whereas

然而

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


fmaxcan be emulated with the following code

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);
}

This shows that std::maxis a subset of fmax.

这表明std::max是 的子集fmax

Looking at the assembly shows that Clang uses builtin code for fmaxand fminwhereas GCC calls them from a math library. The assembly for clang for fmaxwith -O3is

查看程序集显示 Clang 使用内置代码fmaxfmin而 GCC 从数学库调用它们。clang for fmaxwith的程序集-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

whereas for std::max(double, double)it is simply

而因为std::max(double, double)它只是

maxsd   xmm0, xmm1

However, for GCC and Clang using -Ofastfmaxbecomes simply

但是,对于 GCC 和 Clang 使用-Ofastfmax变得简单

maxsd   xmm0, xmm1

So this shows once again that std::maxis a subset of fmaxand that when you use a looser floating point model which does not have nanor signed zero then fmaxand std::maxare the same. The same argument obviously applies to fminand std::min.

所以这再次表明这std::max是一个子集fmax,当你使用一个更松散的浮点模型时,它没有nan或没有符号零,fmax并且std::max是相同的。同样的论点显然适用于fminstd::min

回答by J Ridges

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.

您错过了 fmin 和 fmax 的全部内容。它包含在 C99 中,以便现代 CPU 可以使用其原生(读取 SSE)指令进行浮点最小值和最大值,并避免测试和分支(因此可能是错误预测的分支)。我已经重新编写了使用 std::min 和 std::max 的代码,以在内部循环中使用 SSE 内在函数的 min 和 max ,并且加速非常显着。

回答by sellibitze

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:

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
}

As for performance, I don't think fminand fmaxdiffer from their C++ counterparts.

至于性能,我不认为fminfmax他们的 C++ 同行不同。

回答by Jerry Coffin

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.

如果您的实现提供 64 位整数类型,您可能会通过使用 fmin 或 fmax 得到不同(不正确)的答案。您的 64 位整数将转换为双精度数,这将(至少通常)具有小于 64 位的有效数。当您将这样的数字转换为双精度数时,一些最低有效位可能/将完全丢失。

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.

这意味着两个真正不同的数字在转换为 double 时最终可能相等——结果将是那个不正确的数字,它不一定等于原始输入中的任何一个。

回答by Eric Melski

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.

如果您使用 C++,我更喜欢 C++ min/max 函数,因为它们是特定于类型的。fmin/fmax 将强制将所有内容转换为浮点数/从浮点数转换。

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

此外,只要您为这些类型定义了 operator<,C++ min/max 函数就可以使用用户定义的类型。

HTH

HTH

回答by AnT

As you noted yourself, fminand fmaxwere introduced in C99. Standard C++ library doesn't have fminand fmaxfunctions. 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.

正如您自己指出的那样,fmin并且fmax是在 C99 中引入的。标准 C++ 库没有fminfmax函数。在 C99 标准库被并入 C++(如果有的话)之前,这些函数的应用领域是完全分开的。在任何情况下,您都可能不得不“偏爱”一个而不是另一个。

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

您只需在 C++ 中使用模板化std::min/ std::max,并使用 C 中可用的任何内容。

回答by mloskot

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.

正如 Richard Corden 所指出的,使用 std 命名空间中定义的 C++ 函数 min 和 max。它们提供类型安全,并有助于避免比较混合类型(即浮点与整数)有时可能是不受欢迎的。

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):

如果你发现你使用的 C++ 库也将 min/max 定义为宏,它可能会导致冲突,那么你可以防止不需要的宏替换以这种方式调用 min/max 函数(注意额外的括号):

(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.

请记住,这将有效地禁用参数相关查找(ADL,也称为 Koenig 查找),以防您想依赖 ADL。

回答by user3405743

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

针对具有 SSE 指令的处理器的 C++ 实现不能为floatdoublelong double类型提供std::minstd::max 的特化,它们分别相当于fminffminfminl吗?

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.

特化将为浮点类型提供更好的性能,而通用模板将处理非浮点类型,而不会像fmins 和fmaxes 那样试图将浮点类型强制转换为浮点类型。

回答by Richard Corden

Use std::minand std::max.

使用std::minstd::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);
}