【问题标题】:Limit integer to bounds [duplicate]将整数限制在范围内[重复]
【发布时间】:2017-05-22 23:31:11
【问题描述】:

我正在尝试确保 int x 大于或等于 0 但小于 1080(在这种情况下为屏幕尺寸)。

我想出了这个

int x = 123;
x = std::min(std::max(x, 0), 1080);

这看起来很难看。有没有更好的方法来实现这一点?

【问题讨论】:

标签: c++ max min clamp


【解决方案1】:

如果你生活在未来,你可以使用std::clamp from C++17

x = std::clamp(x, 0, 1080);

【讨论】:

  • 未来的加一!从未来的标准中包含好的 sn-ps 并没有什么坏处。
  • 好的,谢谢,这主要是我想要的。我会保留最小/最大组合,直到未来到来
  • @Eric:嗯??只需编写自己的包装器,然后在时机成熟时将其替换为夹子......
【解决方案2】:

简单的解决方案看起来也不错:

int x = 123;
if (x < 0)
    x = 0;
if (x > 1080)
    x = 1080;

或将所有内容包装在一个函数中:

template<typename T>
T between(const T x, const T min, const T max){
   if (x < min)
       return min;

   if (x > max)
       return max;

   return x;
}

int x = between(123, 0, 1080);

【讨论】:

  • 代码已修复,抱歉
  • 写起来相当简单,读起来超级简单......当问题真的很简单时,不需要超级复杂的 C++17 东西。我的首选方式!
【解决方案3】:

使用无符号作为 x 的类型。这会自动将其限制为非负数。

那么你只剩下对 std::min 的调用了,这至少对我来说是可以接受的。

构建一个在构造上采用 int 并具有转换运算符到 int 的类也是可行的,但需要相当多的样板。

【讨论】:

  • 这是个好主意,但不幸的是 x 是通过 API 回调获取的,因此我无法轻松更改类型。当然我可以将 int 转换为 unsigned int,但这也很丑 imo
【解决方案4】:

为什么不做这样的事情呢?

int x = 123; /* Or some arbitrary number */
bool bIsInRange = (x >= 0) && (x < 1080);
if(!bIsInRange){
   std::cout << "Variable 'x' is not between 0 and 1080." << std::endl;
   return 1;
} // else, x is fine. Continue operations as normal.

【讨论】:

  • 看起来超级难看。
  • @melpomene,然而,对于任何经验水平的任何人来说,它都是标准的、可读的和极易理解的。此外,以这种正常方式执行此操作不需要额外调用诸如minmaxclamp 之类的函数,这只会增加原本简单且基本上没有重量的任务的开销/费用。话虽如此,我同意这绝不是“美丽”。
  • 我觉得它不可读。主要问题是bIsInRange 变量,它没有任何作用,而且名字很糟糕。至于开销,我希望编译器能够内联 min/max/clamp。 (如果我们谈论效率,cout &lt;&lt; "..." &lt;&lt; endl 构造可能比普通函数调用慢 100 倍。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
  • 2022-11-14
相关资源
最近更新 更多