从C ++开始,minmax优先于fminfmax?为了比较两个整数,它们是否提供基本相同的功能?

您是倾向于使用这些功能集中的一种还是更喜欢自己编写(可能是为了提高效率,可移植性,灵活性等)?

<强> 注意:

  1. C ++标准模板库(STL)声明标准C ++中的<=>和<=>函数算法标题。

  2. C标准(C99)在标准C中提供<=>和<=>函数 math.h 标题。

  3. 提前致谢!

其他提示

std::minstd::maxfmin以及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

所以x ! = NaN不是1-1替代-O3。函数std::max(double, double)-Ofast不可交换。要使用nan和<=>双打来获得相同的结果,应该交换参数

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

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


还有另一个重要的区别。对于<=>:

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

<=>可以使用以下代码进行模拟

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

这表明<=>是<=>的子集。

查看程序集显示Clang使用<=>和<=>的内置代码,而GCC从数学库中调用它们。 <=>与<=>的clang组合是

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

而对于<=>,它只是

maxsd   xmm0, xmm1

然而,对于GCC和Clang使用<=> <=>变得简单

<*>

因此,再次显示<=>是<=>的子集,并且当您使用没有<=>或符号为零的宽松浮点模型时,<=>和<=>是相同的。同样的论点显然适用于<=>和<=>。

你错过了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
}

至于性能,我认为fminfmax与C ++对应的不同。

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

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

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

此外,只要您定义了operator <!> lt; C ++ min / max函数将使用用户定义的类型。对于那些类型。

HTH

正如您自己所说,fminfmax是在C99中引入的。标准C ++库没有std::minstd::max函数。直到C99标准库被合并到C ++中(如果有的话),这些函数的应用程序区域被完全分开。在任何情况下你都不必<!>“;更喜欢<!>”;一个在另一个上面。

您只需在C ++中使用模板化<=> / <=>,并使用C中可用的任何内容。

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

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

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

请记住,这将有效禁用 Argument Dependent Lookup (ADL,也称为Koenig查找) ,如果你想依赖ADL。

fmin和fmax仅适用于浮点和双变量。

min和max是模板函数,允许在给定二元谓词的情况下比较任何类型。它们还可以与其他算法一起使用,以提供复杂的功能。

使用std::minstd::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 ++实现无法为类型 float std :: min std :: max 的特化>, double long double ,相当于 fminf fmin fminl ,分别?

特殊化将为浮点类型提供更好的性能,而通用模板将处理非浮点类型而不尝试将浮点类型强制转换为浮点类型,就像 fmin 一样s和 fmax es会。

我总是使用最小和最大宏进行整数。我不确定为什么有人会使用fmin或fmax作为整数值。

最小和最大的大问题是它们不是功能,即使它们看起来像它们。如果您执行以下操作:

min (10, BigExpensiveFunctionCall())

根据宏的实现,可能会调用两次函数调用。因此,我的组织中的最佳做法是永远不要使用非文字或变量的东西来调用min或max。

在比较有符号和无符号整数时,fmin fmaxfminlfmaxl和<=>可能是首选 - 您可以利用整个有符号和无符号数的范围,而不是不得不担心整数范围和促销。

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

int z = min(x, y);
z = (int)fmin(x, y);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top