Cog*_*eel 107
fmin
并且fmax
特别适用于浮点数(因此为"f").如果将其用于整数,则可能会因转换,函数调用开销等而导致性能或精度损失,具体取决于您的编译器/平台.
std::min
并且std::max
是模板函数(在标题中定义<algorithm>
),它适用于任何具有less-than(<
)运算符的类型,因此它们可以对允许这种比较的任何数据类型进行操作.如果您不想让它起作用,您也可以提供自己的比较功能<
.
这更安全,因为当它们具有不同类型时必须显式转换参数以匹配.例如,编译器不会让您意外地将64位int转换为64位浮点数.仅此原因应该使模板成为您的默认选择.(感谢Matthieu M&bk1e)
即使与浮动一起使用,模板也可能在性能上获胜.编译器始终可以选择内联对模板函数的调用,因为源代码是编译单元的一部分.有时,不可能内联对库函数的调用(共享库,缺少链接时优化等).
Z b*_*son 32
有一个重要区别std::min
,std::max
和fmin
和fmax
.
std::min(-0.0,0.0) = -0.0
std::max(-0.0,0.0) = -0.0
Run Code Online (Sandbox Code Playgroud)
而
fmin(-0.0, 0.0) = -0.0
fmax(-0.0, 0.0) = 0.0
Run Code Online (Sandbox Code Playgroud)
所以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)
Run Code Online (Sandbox Code Playgroud)
但据我所知,所有这些功能都是在这种情况下定义的实现,所以要100%确定你必须测试它们是如何实现的.
还有另一个重要的区别.用于x ! = NaN
:
std::max(Nan,x) = NaN
std::max(x,NaN) = x
std::min(Nan,x) = NaN
std::min(x,NaN) = x
Run Code Online (Sandbox Code Playgroud)
而
fmax(Nan,x) = x
fmax(x,NaN) = x
fmin(Nan,x) = x
fmin(x,NaN) = x
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
这表明它std::max
是一个子集fmax
.
查看程序集显示Clang使用内置代码fmax
,fmin
而GCC从数学库中调用它们.用于铛的组件,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
Run Code Online (Sandbox Code Playgroud)
而std::max(double, double)
它简直就是这样
maxsd xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)
然而,对于GCC和Clang使用-Ofast
fmax
变得简单
maxsd xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)
因此,这再次表明std::max
的一个子集fmax
,并且当您使用不具有较宽松的浮点模型nan
或再签署零fmax
和std::max
是相同的.同样的论点显然适用于fmin
和std::min
.
小智 16
你错过了fmin和fmax的整个点.它包含在C99中,因此现代CPU可以使用其本机(读取SSE)指令来实现浮点最小值和最大值,并避免测试和分支(因此可能是错误预测的分支).我重写了使用std :: min和std :: max的代码,在内部循环中使用SSE内在函数来获取min和max,而且加速很快.
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
}
Run Code Online (Sandbox Code Playgroud)
至于性能,我不认为fmin
和fmax
他们的C++对应物不同.
如果您的实现提供64位整数类型,则可以使用fmin或fmax获得不同(不正确)的答案.您的64位整数将转换为双精度数,它将(至少通常)具有小于64位的有效位数.当您将这样的数字转换为double时,一些最低有效位可能/将完全丢失.
这意味着两个真正不同的数字在转换为double时最终会相等 - 结果将是不正确的数字,这不一定等于任何一个原始输入.