55 votes

Le moyen le plus efficace/élégant de couper un numéro ?

Étant donné un réel (n), une valeur maximale que ce réel peut être (supérieure) et une valeur minimale que ce réel peut être (inférieure), comment pouvons-nous le plus efficacement couper n, de sorte qu'il reste entre inférieur et supérieur ?

Bien sûr, utiliser un tas d'instructions if peut le faire, mais c'est ennuyeux ! Qu'en est-il des solutions plus compactes et élégantes/amusantes ?

Ma propre tentative rapide (C/C++):

 float clip( float n, float lower, float upper )
{
    n = ( n > lower ) * n + !( n > lower ) * lower;
    return ( n < upper ) * n + !( n < upper ) * upper;
}

Je suis sûr qu'il y a d'autres meilleures façons de le faire, c'est pourquoi je mets ça là-bas ..!

95voto

justin Points 72871

Qu'en est-il ennuyeux, vieux, lisible et le plus court à ce jour :

 float clip(float n, float lower, float upper) {
  return std::max(lower, std::min(n, upper));
}

?

Cette expression pourrait également être «générisée» comme suit :

 template <typename T>
T clip(const T& n, const T& lower, const T& upper) {
  return std::max(lower, std::min(n, upper));
}

Mettre à jour

Billy ONeal a ajouté :

Notez que sous Windows, vous devrez peut-être définir NOMINMAX car ils définissent des macros min et max qui sont en conflit

61voto

Riot Points 618

Pourquoi réécrire quelque chose qui a déjà été écrit pour vous ?

 #include <boost/algorithm/clamp.hpp>
boost::algorithm::clamp(n, lower, upper);

Depuis C++17, cela fait maintenant partie de la STL :

 #include <algorithm>
std::clamp(n, lower, upper);

24voto

Josh Kelley Points 24438

C++17 devrait ajouter une fonction de serrage. Avec l'aimable autorisation de cppreference.com :

 template<class T>
constexpr const T& clamp( const T& v, const T& lo, const T& hi );

template<class T, class Compare>
constexpr const T& clamp( const T& v, const T& lo, const T& hi, Compare comp );

6voto

Yves Daoust Points 6396

Inélégant, dangereux, coûteux mais sans branches :

 n= 0.5 * (n + lower + fabs(n - lower));
n= 0.5 * (n + upper - fabs(upper - n));

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X