【问题标题】:How can I write a 'clamp' / 'clip' / 'bound' macro for returning a value in a given range?如何编写“clamp”/“clip”/“bound”宏来返回给定范围内的值?
【发布时间】:2013-01-24 01:03:03
【问题描述】:

我经常发现自己在写类似的东西

int computedValue = ...;
return MAX(0, MIN(5, computedValue));

我希望能够把它写成一个单行宏。它必须没有副作用,就像现有系统宏 MIN 和 MAX 一样,并且应该适用于与 MIN 和 MAX 相同的数据类型。

谁能告诉我如何把它变成一个宏?

【问题讨论】:

  • 你不能简单地这样做,定义一个最小-最大宏,使用最小和最大宏吗?还是我误解了你的问题?
  • 通常称为clamp
  • 只是出于好奇,有什么理由不使用 C++ 标准库中的 std::min 和 std::max 吗?
  • @ybungalobill 或绑定,或裁剪,或......我认为最常见的面额取决于应用程序域。
  • 那么,也许可以去掉 C++ 标签,因为 C++ 程序员倾向于避免使用宏,特别是如果标准库提供了更好的解决方案。

标签: objective-c c macros predefined-macro


【解决方案1】:

也许你想这样尝试:

template <class T> 
const T& clamp(const T& value, const T& low, const T& high) {
    return value < low ? low:
           value > high? high:
                         value;
}

【讨论】:

  • return std::max( low, std::min( high, value ) );
【解决方案2】:

只使用一个比较操作:

static inline int clamp(int value, int min, int max) {
    return min + MIN((unsigned int)(value - min), max - min)
}

【讨论】:

  • 好吧。说值的类型可以改变 - 我更喜欢宏?你同意吗?
  • 是的,需要一些方法来使“unsigned typeof”变成宏。
  • 另一方面,假设我们只使用整数类型,#define CLAMP(x, low, high) ({ typeof(low) _low = (low); LARGE_ENOUGH_UNSIGNED_TYPE _x = (x) - _low, _high = (high) - _low; (typeof(x)) MIN(_x, _high); })
【解决方案3】:
 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 
 #define MIN(a, b) (((a) > (b)) ? (b) : (a))

在一个#define 指令中编写它的可读性并不高。

【讨论】:

    【解决方案4】:

    取自本站http://developer.gnome.org/glib/2.34/glib-Standard-Macros.html#CLAMP:CAPS

    #define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
    

    【讨论】:

    【解决方案5】:

    这没有副作用,适用于任何原始数字:

    #define MIN(A,B)    ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
    #define MAX(A,B)    ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
    
    #define CLAMP(x, low, high) ({\
      __typeof__(x) __x = (x); \
      __typeof__(low) __low = (low);\
      __typeof__(high) __high = (high);\
      __x > __high ? __high : (__x < __low ? __low : __x);\
      })
    

    可以这样使用

    int clampedInt = CLAMP(computedValue, 3, 7);
    double clampedDouble = CLAMP(computedValue, 0.5, 1.0);
    

    替代CLAMP 的其他建议名称可以是VALUE_CONSTRAINED_LOW_HIGHBOUNDSCLIPPED

    【讨论】:

      猜你喜欢
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-05
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      相关资源
      最近更新 更多