std::min/std::max 和 fmin/fmax 有什么区别?
在 C++ 中,std::min
和 std::max
是否优于 fmin
和 fmax
?为了比较两个整数,它们提供基本相同的功能吗?
您是否倾向于使用这些函数集中的一组,还是更喜欢编写自己的函数(也许是为了提高效率、可移植性、灵活性等)?
注释
C++ 标准模板库 (STL) 在标准 C++ 中声明了
min
和max
函数算法
标头。C 标准 (C99) 提供了标准 C 中的
fmin
和fmax
函数math.h
标头(在 C++11 中也提供为std::fmin
和cmath
a> 标题)。
In C++, are std::min
and std::max
preferable over fmin
and fmax
? For comparing two integers, do they provide basically the same functionality?
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
fmin
和fmax
专门用于浮点数(因此称为“f”)。如果将其用于整数,则可能会因转换、函数调用开销等而遭受性能或精度损失,具体取决于您的编译器/平台。std::min
和std::max
是模板函数(在标头
) 适用于任何带有小于 (<
) 运算符的类型,因此它们可以对任何允许进行此类比较的数据类型进行操作。如果您不希望它在<
之外工作,您也可以提供自己的比较函数。这更安全,因为当参数具有不同类型时,您必须显式转换参数以进行匹配。例如,编译器不会让您意外地将 64 位 int 转换为 64 位 float。仅凭这个原因就应该使模板成为您的默认选择。 (归功于 Matthieu M & bk1e)
即使与浮动一起使用,模板也可能在性能上获胜。由于源代码是编译单元的一部分,因此编译器始终可以选择内联调用模板函数。另一方面,有时不可能内联对库函数的调用(共享库、缺少链接时优化等)。
fmin
andfmax
are 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.std::min
andstd::max
are 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<
.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)
Even when used with floats the template may win 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 impossible to inline a call to a library function, on the other hand (shared libraries, absence of link-time optimization, etc.).
std::min
、std::max
以及fmin
和fmax
之间存在重要区别。而
So
std::min
并不是fmin
的 1-1 替代品。函数std::min
和std::max
不可交换。要使用fmin
和fmax
获得相同的结果,应该交换参数但据我所知 在这种情况下,所有这些函数都是实现定义的,因此要 100% 确定您必须进行测试它们是如何实施的。
还有另一个重要的区别。对于
x! = NaN
:而
fmax
可以用以下代码来模拟std::max
是fmax
的子集,因为它只需要第一个比较 (x < y
)。查看程序集可以发现,Clang 使用
fmax
和fmin
的内置代码,而 GCC 从数学库中调用它们。带有-O3
的fmax
的 clang 的汇编是,而对于
std::max(double, double)
来说,它很简单但是,对于 GCC 和Clang 使用
-Ofast
fmax
变得简单所以这再次表明
std::max
是fmax
的子集当您使用没有 nan 或符号零的宽松浮点模型时,fmax 和 std::max 是相同的。同样的论点显然也适用于fmin
和std::min
。There is an important difference between
std::min
,std::max
andfmin
andfmax
.whereas
So
std::min
is not a 1-1 substitute forfmin
. The functionsstd::min
andstd::max
are not commutative. To get the same result with doubles withfmin
andfmax
, one should swap the argumentsBut as far as I can tell all these functions are implementation defined anyway in this case so to be 100% sure you have to test how they are implemented.
There is another important difference. For
x ! = NaN
:whereas
fmax
can be emulated with the following codestd::max
is a subset offmax
because it only needs the first comparison (x < y
).Looking at the assembly shows that Clang uses builtin code for
fmax
andfmin
whereas GCC calls them from a math library. The assembly for clang forfmax
with-O3
iswhereas for
std::max(double, double)
it is simplyHowever, for GCC and Clang using
-Ofast
fmax
becomes simplySo this shows once again that
std::max
is a subset offmax
and that when you use a looser floating point model which does not havenan
or signed zero thenfmax
andstd::max
are the same. The same argument obviously applies tofmin
andstd::min
.您错过了 fmin 和 fmax 的全部要点。它包含在 C99 中,以便现代 CPU 可以使用其本机(读取 SSE)指令来计算浮点最小值和最大值,并避免测试和分支(从而避免可能错误预测的分支)。我重写了使用 std::min 和 std::max 的代码,以在内部循环中使用 SSE 内在函数来表示 min 和 max,并且加速效果显着。
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 和 std::max 是模板。因此,它们可用于提供小于运算符的各种类型,包括浮点数、双精度数、长双精度数。因此,如果您想编写通用的 C++ 代码,您可以这样做:
至于性能,我认为
fmin
和fmax
与 C++ 对应的代码没有什么不同。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:
As for performance, I don't think
fmin
andfmax
differ from their C++ counterparts.如果您的实现提供 64 位整数类型,则使用 fmin 或 fmax 可能会得到不同(不正确)的答案。您的 64 位整数将被转换为双精度数,其(至少通常)具有小于 64 位的有效数字。当您将这样的数字转换为双精度数时,一些最低有效位可能/将完全丢失。
这意味着两个完全不同的数字在转换为 double 时可能最终相等 - 结果将是错误的数字,不一定等于任何一个原始输入。
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.
如果您使用 C++,我更喜欢 C++ 最小/最大函数,因为它们是特定于类型的。 fmin/fmax 将强制所有内容转换为浮点或从浮点转换。
此外,只要您定义了运算符<,C++ min/max 函数就可以使用用户定义的类型。对于那些类型。
华泰
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
正如 Richard Corden 指出的,使用 std 命名空间中定义的 C++ 函数 min 和 max 。它们提供类型安全性,并有助于避免比较混合类型(即浮点与整数),这有时可能是不需要的。
如果您发现您使用的 C++ 库也将 min/max 定义为宏,则可能会导致冲突,那么您可以通过这种方式防止不需要的宏替换调用 min/max 函数(注意额外的括号):
记住,这将有效禁用 < a href="http://en.wikipedia.org/wiki/Argument_dependent_name_lookup" rel="nofollow noreferrer">参数相关查找(ADL,也称为 Koenig 查找),以防您想依赖 ADL。
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):
Remember, this will effectively disable Argument Dependant Lookup (ADL, also called Koenig lookup), in case you want to rely on ADL.
正如您自己所指出的,
fmin
和fmax
是在 C99 中引入的。标准 C++ 库没有fmin
和fmax
函数。在 C99 标准库并入 C++ 之前(如果有的话),这些函数的应用领域是完全分开的。在任何情况下,您都可能必须“偏爱”其中一种而不是另一种。您只需在 C++ 中使用模板化的
std::min
/std::max
,并使用 C 中可用的任何内容。As you noted yourself,
fmin
andfmax
were introduced in C99. Standard C++ library doesn't havefmin
andfmax
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.顺便说一句,在
cstdlib
中,您可以使用__min
和__max
。有关更多信息: http://msdn.microsoft.com/zh-cn/library/ btkhtd8d.aspx
By the way, in
cstdlib
there are__min
and__max
you can use.For more: http://msdn.microsoft.com/zh-cn/library/btkhtd8d.aspx
fmin 和 fmax 仅适用于浮点和双精度变量。
min 和 max 是模板函数,允许在给定二元谓词的情况下比较任何类型。它们还可以与其他算法一起使用以提供复杂的功能。
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.
使用
std::min
和std::max
。如果其他版本更快,那么您的实现可以为这些版本添加重载,您将获得性能和可移植性的好处:
Use
std::min
andstd::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:
针对具有 SSE 指令的处理器的 C++ 实现无法为 float、< strong>double 和 long double 相当于 fminf、fmin 和 fminl , 分别?
专业化将为浮点类型提供更好的性能,而通用模板将处理非浮点类型,而不会尝试将浮点类型强制转换为浮点类型,即 fmin 和 < fmax 会。
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.
简而言之,
std::max
是
库中的一个“通用函数”,它只是根据< 来选择两个参数中较小的一个。
运算符,而std::fmax
特定于浮点数,并将 NaN 视为缺失数据。std::fmax
/std::fmin
- C++23 标准:[cmath.syn] p1
- C17 标准:F.10.9 .2 fmax 函数
还值得注意的是,
fmax
/fmin
可能对零的符号敏感:- C17 标准:脚注 380
std::max
/std ::分钟
- [alg.min.max]
std::max
标准中没有示例实现,但可能的实现如下所示:
选择哪一个
出于性能原因,最好使用
std::max
和 <代码>std::min。在现代 x86_64 上,
std::max
编译为单个指令...而
std::fmax
编译为参见 编译器资源管理器。
如果操作数不可能为 NaN,则应选择
std::max
/std::min
。否则,使用std::fmax
/std::fmin
。关于汇编的进一步说明
std::fmax(x, y)
不能仅使用vmaxss dest, y, x
实现,因为如果x
或 < code>y 为 NaN,dest = x
。std::fmax
选择x
或y
,具体取决于哪一个不是 NaN。vmaxss
在所有可能的方面都偏向于x
。但是,
vmaxss
与x
x
的行为相匹配。是吗? y : x
和std::max
完全一样。In short,
std::max
is a "generic function" from the<algotithm>
library that simply chooses the lower of two arguments according to the<
operator, whereasstd::fmax
is specific to floating-point numbers and treats NaN as missing data.std::fmax
/std::fmin
- C++23 standard : [cmath.syn] p1
- C17 standard: F.10.9.2 The fmax functions
It's also worth noting that
fmax
/fmin
may be sensitive to the sign of zero:- C17 standard: footnote 380
std::max
/std::min
- [alg.min.max]
std::max
There is no sample implementation in the standard, but a possible implementation looks like:
Which one to choose
For performance reasons, it is better to use
std::max
andstd::min
.On modern x86_64,
std::max
compiles to a single instruction... whereas
std::fmax
compiles toSee Compiler Explorer.
If there's no possibility of operands being NaN, you should go for
std::max
/std::min
. Otherwise, usestd::fmax
/std::fmin
.Further Notes on Assembly
std::fmax(x, y)
cannot be implemented using onlyvmaxss dest, y, x
because ifx
ory
is NaN,dest = x
.std::fmax
choosesx
ory
depending on which one isn't NaN.vmaxss
is biased towardsx
in every possible way.However,
vmaxss
matches the behavior ofx < y ? y : x
and thusstd::max
exactly.我总是对整数使用 min 和 max 宏。我不确定为什么有人会使用 fmin 或 fmax 作为整数值。
min 和 max 的最大问题是它们不是函数,即使它们看起来像函数。如果您执行以下操作:
该函数调用可能会被调用两次,具体取决于宏的实现。因此,我的组织中的最佳实践是永远不要使用非文字或变量的内容调用 min 或 max 。
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:
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.
在比较有符号和无符号整数时,可以首选
fminl
和fmaxl
中的fmin
和fmax
- 您可以利用事实上,有符号和无符号数字的整个范围,您不必担心整数范围和提升。fmin
andfmax
, offminl
andfmaxl
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.主要区别在于它们所操作的值的类型。
std::min
和std::max
更通用,可以与各种数据类型一起使用,而fmin
和fmax< /code> 是专门为浮点数设计的。如果您使用整数或其他类型,则应使用
std::min
和std::max
。The key difference is in the types of values they operate on.
std::min
andstd::max
are more general and can be used with various data types, whilefmin
andfmax
are specifically designed for floating-point numbers. If you are working with integers or other types, you should usestd::min
andstd::max
.