Most efficient/elegant way to clip a number?

前端 未结 11 670
予麋鹿
予麋鹿 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:21

    The following header file should work for C and C++. Note that it undefines min and max if the macros are already defined:

    #pragma once
    
    #ifdef min
    #undef min
    #endif
    
    #ifdef max
    #undef max
    #endif
    
    #ifdef __cplusplus
    #include <algorithm>
    
    template <typename T>
    T clip(T in, T low, T high)
    {
        return std::min(std::max(in, low), high);
    }
    #else /* !__cplusplus */
    #define min(a, b) (((a) < (b)) ? (a) : (b))
    #define max(a, b) (((a) < (b)) ? (b) : (a))
    #define clip(a, b, c) min(max((a), (b)), (c))
    #endif /* __cplusplus */
    
    0 讨论(0)
  • 2020-11-30 03:23

    Inelegant, unsafe, costly but branchless:

    n= 0.5 * (n + lower + fabs(n - lower));
    n= 0.5 * (n + upper - fabs(upper - n));
    
    0 讨论(0)
  • 2020-11-30 03:23

    the best is clearly

    template <typename t>
    t clamp2(t x, t min, t max)
    {
    if (x < min) x = min;
    if (x > max) x = max;
    return x;
    }
    

    as it compiles to

    movss   xmm0, cs:__real@c2c80000
    maxss   xmm0, [rsp+38h+var_18]
    movss   xmm1, cs:__real@42c80000
    minss   xmm1, xmm0
    movss   [rsp+38h+var_18], xmm1
    

    it has 0 branches and should be the fastest of all posted above.

    also msvc141 with the standard release settings

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

    Why rewrite something that's already been written for you?

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

    As of C++17, this is now part of the STL:

    #include <algorithm>
    std::clamp(n, lower, upper);
    
    0 讨论(0)
  • 2020-11-30 03:34
    n = n + ((n < lower) * (lower - n)) + ((n > upper) * (upper - n));
    
    0 讨论(0)
  • 2020-11-30 03:35

    If you wish to use xtensor, it would support multi-dimensional arrays and the solution would be very elegant.

    #include <iostream>
    #include "xtensor/xarray.hpp"
    #include "xtensor/xio.hpp"
    #include "xtensor/xview.hpp"
    #include "xtensor/xrandom.hpp"
    xt::xarray<float> ar({2.1, 2.9, -2.1, -2.9});
    std::cout<<xt::cast<int>(xt::trunc(ar))<<std::endl;
    

    //Answer is { 2, 2, -2, -2 }

    0 讨论(0)
提交回复
热议问题