Most efficient/elegant way to clip a number?

前端 未结 11 671
予麋鹿
予麋鹿 2020-11-30 03:09

Given a real (n), a maximum value this real can be (upper), and a minimum value this real can be (lower), how can we most efficiently clip n, such that it remains between lo

相关标签:
11条回答
  • 2020-11-30 03:39

    If performance really matters to you, what about an inline solution that avoids assignment when not required:

    #define clip(n, lower, upper) if (n < lower) n= lower; else if (n > upper) n= upper
    
    0 讨论(0)
  • 2020-11-30 03:42

    UPDATE: C++17's <algorithm> header added std::clamp(value, low, high).

    In older C++ versions, I'd very rarely go beyond...

    return n <= lower ? lower : n >= upper ? upper : n;
    

    ...or, if you find it more readable keeping the left-to-right ordering of lower, n and upper...

    return n <= lower ? lower : n <= upper ? n : upper;
    

    (using <= lower is better than < lower because when n == lower it avoids having to compare with upper)

    If you know you might have them, you'd want to check if NaN / Inf etc. are preserved....

    I say rarely and not never just because sometimes less branching can be faster, but you'd sure want to profile it and prove it helped and mattered....

    0 讨论(0)
  • 2020-11-30 03:45

    C++17 is expected to add a clamp function. Courtesy of 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 );
    
    0 讨论(0)
  • 2020-11-30 03:46

    What about boring, old, readable, and shortest yet:

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

    ?

    This expression could also be 'genericized' like so:

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

    Update

    Billy ONeal added:

    Note that on windows you might have to define NOMINMAX because they define min and max macros which conflict

    0 讨论(0)
  • 2020-11-30 03:46

    You might like the ternary operator:

    value = value<lower?lower:value;
    value = value>upper?upper:value;
    
    0 讨论(0)
提交回复
热议问题