Frage

Von C ++, sind min und max bevorzugt über fmin und fmax? Für zwei ganze Zahlen zu vergleichen, haben sie grundsätzlich die gleiche Funktionalität zur Verfügung stellen?

Haben Sie neigen dazu, eine dieser Gruppen von Funktionen zu nutzen oder möchten Sie lieber Ihre eigenen (vielleicht verbessern Effizienz, Portabilität, Flexibilität, etc.) Schreiben?

Weitere Informationen:

  1. Die C ++ Standard Template Library (STL) deklariert die min und max Funktionen in der Standard-C ++ Algorithmus Header.

  2. Der C-Standard (C99) stellt die fmin und fmax Funktion in der Standard-C math .h Header.

Vielen Dank im Voraus!

War es hilfreich?

Lösung

fmin fmax und sind speziell für die Verwendung mit Gleitkommazahlen (daher der „f“). Wenn Sie es für ints verwenden, können Sie die Leistung oder Genauigkeit Verluste erleiden aufgrund der Umwandlung, Funktionsaufruf Overhead etc. abhängig von der Compiler / Plattform.

std::min und std::max sind Template-Funktionen (definiert in Header <algorithm> ), die Arbeit auf jeder Art mit einem weniger-als (<) Betreiber, so dass sie auf einem beliebigen Datentyp arbeiten, die einen solchen Vergleich ermöglicht. Sie können auch Ihre eigene Vergleichsfunktion zur Verfügung stellen, wenn Sie es < abzuarbeiten nicht wollen.

Dies ist sicherer, da Sie müssen explizit Argumente konvertieren anpassen, wenn sie unterschiedliche Typen haben. Der Compiler lassen Sie nicht aus Versehen ein 64-Bit-int in einen 64-Bit-Float zum Beispiel konvertieren. Allein aus diesem Grund sollten die Vorlagen, um Ihre Standard-Wahl. (Credit Matthieu M & bk1e)

Auch wenn mit Schwimmern die Vorlage verwendet können in der Leistung gewinnen. Ein Compiler hat immer die Möglichkeit, inlining ruft Funktionen auf Vorlage, da der Quellcode Teil der Übersetzungseinheit ist. Manchmal ist es unmöglich einen Aufruf einer Bibliotheksfunktion Inline, auf der anderen Seite (Shared Libraries, das Fehlen von Link-Zeitoptimierung, etc.).

Andere Tipps

Es gibt einen wichtigen Unterschied zwischen std::min, std::max und fmin und fmax.

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

während

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

So std::min kein Ersatz für 1-1 fmin ist. Die Funktionen std::min und std::max sind nicht kommutativ. Um das gleiche Ergebnis mit Doppel mit fmin zu bekommen und fmax sollte man die Argumente tauschen

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

Aber soweit ich das sagen kann all diese Funktionen sind Implementierung ohnehin in diesem Fall definiert so 100% sicher, dass Sie testen müssen, um sein, wie sie umgesetzt werden.


Es ist ein weiterer wichtiger Unterschied. Für x ! = NaN:

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

während

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

fmax kann mit dem folgenden Code emuliert werden

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

Dies zeigt, dass std::max eine Teilmenge von fmax ist.

bei der Montage der Suche zeigt, dass Clang builtin Code für fmax und fmin verwendet, während GCC sie von einer Mathematik-Bibliothek aufruft. Die Anordnung für Klirren für fmax mit -O3 ist

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

während für std::max(double, double) es ist einfach

maxsd   xmm0, xmm1

Doch für GCC und Clang mit -Ofast fmax wird einfach

maxsd   xmm0, xmm1

Also das zeigt einmal mehr, dass std::max ist eine Teilmenge von fmax und dass, wenn Sie verwenden, um eine lockerere Floating-Point-Modell, das nicht nan hat oder unterzeichnet Null dann fmax und std::max sind die gleichen. Das gleiche Argument gilt selbstverständlich für fmin und std::min.

Sie verpassen den ganzen Punkt von fmin und fmax. Es wurde in C99 enthalten, so dass moderne CPUs ihre Mutter nutzen könnten Anweisungen für Gleitkomma-min und max (SSE lesen) und einen Test und Zweig (und damit eine möglicherweise falsch vorhergesagte Verzweigung) vermeiden. Ich habe neu geschrieben Code, std :: verwendet min und std :: max SSE-Spezifika für min und max in inneren Schleifen zu verwenden, anstatt und das Speed-up war signifikant.

std :: min und std :: max sind Vorlagen. So können sie auf eine Vielzahl von Arten verwendet werden, die weniger als Betreiber, einschließlich Schwimmer, Doppel-, lange Doppelzimmer. Also, wenn Sie generische C ++ Code schreiben wollte, würden Sie etwas tun, wie folgt aus:

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
}

Was die Leistung, ich glaube nicht, fmin und fmax von ihren C ++ Pendants unterscheiden.

Wenn Ihre Implementierung eine Art 64-Bit-Integer bietet, können Sie eine andere (falsche) Antwort erhalten, indem fmin oder fmax verwenden. Ihre 64-Bit-Integer wird verdoppelt umgewandelt werden, das wird (zumindest in der Regel) einen Signifikanden hat, die kleiner als 64 Bit ist. Wenn Sie eine solche Nummer zu einem Doppel konvertieren, können einige der am wenigsten signifikanten Bits / vollständig verloren.

Das bedeutet, dass zwei Zahlen, die wirklich anders waren gleich, wenn sie doppelt umgewandelt könnte am Ende - und das Ergebnis wird, dass eine falsche Zahl, das ist nicht unbedingt gleich entweder der ursprünglichen Eingänge

.

Ich würde die C ++ min / max Funktionen bevorzugen, wenn Sie C ++ verwenden, weil sie typspezifisch sind. fmin / fmax wird alles zwingen zum / vom Gleitkomma umgewandelt werden.

Auch die C ++ min / max-Funktionen werden so lange mit benutzerdefinierten Typen arbeiten, wie Sie Operator definiert haben

HTH

Wie Sie selbst bemerkt, fmin und fmax wurden in C99 eingeführt. Standard C ++ Bibliothek ist fmin und fmax nicht funktioniert haben. Bis C99-Standardbibliothek wird in C ++ integriert (wenn überhaupt) sind die Anwendungsbereiche dieser Funktionen sauber getrennt. Es gibt keine Situation, wo Sie vielleicht müssen „lieber“ einen über den anderen.

Sie verwenden nur Templat std::min / std::max in C ++, und verwenden, was auch immer in C zur Verfügung.

Wie Richard Corden hingewiesen, verwenden C ++ Funktionen min und max in std Namensraum definiert. Sie bieten Typsicherheit und helfen Mischtypen zu vermeiden, zu vergleichen (das heißt float Punkt vs integer), was manchmal unerwünscht sein kann.

Wenn Sie feststellen, dass C ++ Bibliothek, die Sie min / max als Makros definiert auch, es zu Konflikten führen kann, dann können Sie unerwünschte Makroersetzung verhindern Aufruf der Min- / Max-Funktionen auf diese Weise (Hinweis zusätzliche Klammern):

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

Denken Sie daran, dies wird effektiv Argument abhängige Lookup (ADL, auch genannt Koenig-Lookup) deaktivieren im Fall möchten Sie auf ADL verlassen.

fmin und fmax sind nur für Punkt und Doppel Variablen schweben.

min und max sind Template-Funktionen, die einen Vergleich von irgendwelchen Typen erlauben, ein binäres Prädikat gegeben. Sie können auch mit anderen Algorithmen verwendet werden, um komplexe Funktionen bereitzustellen.

Mit std::min und std::max.

Wenn die anderen Versionen sind schneller als Ihre Implementierung Überlastungen für diese hinzufügen können, und Sie werden den Nutzen der Leistung und Mobilität erhalten:

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

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

Durch die Art und Weise, in cstdlib gibt es __min und __max Sie verwenden können.

Für mehr: http://msdn.microsoft.com/zh-cn /library/btkhtd8d.aspx

kann nicht ein C ++ Implementierung für Prozessoren mit SSE-Befehlen gezielt bietet Spezialisierungen von std :: min und std :: max für Typen float , Doppel und long double , die das Äquivalent von fminf , fmin und fminl tun bzw.

Die Spezialisierungen würden für eine bessere Leistung bieten-Floating-Point-Typen, während die allgemeine Vorlage nicht-Gleitkommatypen behandeln würde, ohne zu versuchen Gleitkommatypen in Gleitkommatypen auf diese Weise der fmin zu zwingen s und fmax es tun würde.

Ich verwende die Min- und Max-Makros für ints immer. Ich bin nicht sicher, warum jemand fmin verwenden würde oder für ganzzahlige Werte fmax.

Der große Gotcha mit min und max ist, dass sie nicht funktioniert sind, auch wenn sie aussehen wie sie. Wenn Sie so etwas wie:

min (10, BigExpensiveFunctionCall())

Das Funktionsaufruf kann zweimal aufgerufen je nach Implementierung des Makros. Als solche seine beste Praxis in meinem org nie mit den Dingen min oder max aufrufen, die nicht eine wörtliche oder variabel sind.

fmin und fmax, von fminl und fmaxl könnte bevorzugt werden, wenn und ganze Zahlen ohne Vorzeichen unterzeichnet Vergleichens - Sie sich die Tatsache zunutze, dass der gesamte Bereich der mit und ohne Vorzeichen Zahlen nehmen können, und Sie müssen nicht über Integer-Bereiche und Aktionen sorgen .

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

int z = min(x, y);
z = (int)fmin(x, y);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top