你能否在整数(C++)中设置最大限制?

4

如果我不想让一个整数超过100,是否有简单的方法来确保无论用户添加多少,该整数都不会超过100?

例如:

50 + 40 = 90
50 + 50 = 100
50 + 60 = 100
50 + 90 = 100

1
你可以使用三元表达式来强制赋值:n = n > 100 ? 100 : n; - Brandon Moretz
1
已经有一个了 - INT_MAX :-)) - user405725
@sehe,从提供的示例中这应该是显而易见的。 - Mark Ransom
@MarkRansom:没错。我为了好玩和教育目的而发布了一个简单实现的BoundedInt结构体。 - sehe
4
这被称为饱和加法,如果需要,您可以在谷歌上搜索它。请记住,(50+60)-30 ≠ 50+(60-30)。您真的想在每一步都截断结果吗?还是只在最后截断?那么“最后”是什么时候呢? - MSalters
显示剩余5条评论
7个回答

12

试一下这个:

std::min(50 + 40, 100);
std::min(50 + 50, 100);
std::min(50 + 60, 100);
std::min(50 + 90, 100);

http://www.cplusplus.com/reference/algorithm/min/

另一个选择是在每次操作后使用此选项:

if (answer > 100) answer = 100;

1
如果您不想使用STL,您可以定义自己的min函数,例如 template <class T> const T& min ( const T& a, const T& b ) { return !(b<a)?a:b; } - jli
8
为什么不想使用标准库? - John Dibling

7
这里是一个相当简单而完整的示例,用于通用的BoundedInt的简单ADT。
  • 它使用boost / operators来避免编写繁琐的(const,非分配)重载。
  • 隐式转换使其互操作。
  • 我避免了智能优化(因此代码更容易适应例如模数版本,或具有下限的版本)
  • 我还避免了直接模板化重载以转换/操作混合实例(例如将BoundedInt与BoundedInt进行比较),原因是:您可能可以依赖于编译器将其优化为相同的效果

注:

  • 您需要c ++ 0x支持以允许Max的默认值生效( constexpr 支持); 只要手动指定Max,就不需要

以下是一个非常简单的演示。

#include <limits>
#include <iostream>
#include <boost/operators.hpp>

template <
    typename Int=unsigned int, 
    Int Max=std::numeric_limits<Int>::max()>
struct BoundedInt : boost::operators<BoundedInt<Int, Max> >
{
    BoundedInt(const Int& value) : _value(value) {}

    Int get() const { return std::min(Max, _value); }
    operator Int() const { return get(); }

    friend std::ostream& operator<<(std::ostream& os, const BoundedInt& bi)
    { return std::cout << bi.get() << " [hidden: " << bi._value << "]"; }

    bool operator<(const BoundedInt& x) const   { return get()<x.get(); }
    bool operator==(const BoundedInt& x) const  { return get()==x.get(); }
    BoundedInt& operator+=(const BoundedInt& x) { _value = get() + x.get(); return *this; }
    BoundedInt& operator-=(const BoundedInt& x) { _value = get() - x.get(); return *this; }
    BoundedInt& operator*=(const BoundedInt& x) { _value = get() * x.get(); return *this; }
    BoundedInt& operator/=(const BoundedInt& x) { _value = get() / x.get(); return *this; }
    BoundedInt& operator%=(const BoundedInt& x) { _value = get() % x.get(); return *this; }
    BoundedInt& operator|=(const BoundedInt& x) { _value = get() | x.get(); return *this; }
    BoundedInt& operator&=(const BoundedInt& x) { _value = get() & x.get(); return *this; }
    BoundedInt& operator^=(const BoundedInt& x) { _value = get() ^ x.get(); return *this; }
    BoundedInt& operator++() { _value = get()+1; return *this; }
    BoundedInt& operator--() { _value = get()-1; return *this; }
  private:
    Int _value;
};

示例用法:

typedef BoundedInt<unsigned int, 100> max100;

int main()
{
    max100 i = 1;

    std::cout << (i *= 10) << std::endl;
    std::cout << (i *= 6 ) << std::endl;
    std::cout << (i *= 2 ) << std::endl;
    std::cout << (i -= 40) << std::endl;
    std::cout << (i += 1 ) << std::endl;
}

示例输出:

10 [hidden: 10]
60 [hidden: 60]
100 [hidden: 120]
60 [hidden: 60]
61 [hidden: 61]

额外材料:

如果您使用的是完全符合c++11标准的编译器,甚至可以定义一个用户自定义字面量转换:

typedef BoundedInt<unsigned int, 100> max100;

static max100 operator ""_b(unsigned int i) 
{ 
     return max100(unsigned int i); 
}

这样,你就可以编写代码了

max100 x = 123_b;        // 100
int    y = 2_b*60 - 30;  //  70

虽然完整,但除非您确实需要对中间操作进行严格控制,否则没有必要重载每个运算符。我的类更简单,但可以完成相同的任务。 - Mark Ransom
@MarkRansom:我发现很难确定确切需要什么。我也不喜欢引入泄漏的抽象 - 即使是愚蠢的示例代码,最小惊讶原则也应该保持。我打算展示一个通用的有界整数类,你可以从它被声明为模板的方式中轻松看出来。把它当作一个“模具”。我将来可以参考这篇文章。 - sehe
1
哈哈哈,我相信当时我所需要的只是一个简单的if语句。我想我应该是在上我的第一门编程课时问过这个问题。但是感谢你详细的回答(虽然已经晚了5年)! - Max O'Neill

2

是的。

作为最基本的内容,你可以从这里开始:

template <int T>
class BoundedInt
{
public:
  explicit BoundedInt(int startValue = 0) : m_value(startValue) {}
  operator int() { return m_value; }

  BoundedInt operator+(int rhs)
    { return BoundedInt(std::min((int)BoundedInt(m_value + rhs), T)); }

private:
  int m_value;
};

0
最简单的方法是创建一个类来保存值,而不是使用整数变量。
class LimitedInt
{
    int value;
public:
    LimitedInt() : value(0) {}
    LimitedInt(int i) : value(i) { if (value > 100) value = 100; }
    operator int() const { return value; }
    LimitedInt & operator=(int i) { value = i; if (value > 100) value = 100; return *this; }
};

你可能会遇到结果与期望不符的麻烦。这个结果应该是70还是90?

LimitedInt q = 2*60 - 30;

0

你可以编写自己的类IntegerRange,其中包括重载operator+operator-等运算符。关于运算符重载的示例,请参见complex类此处


0

C++不允许在基本类型上覆盖(重新定义)运算符。

如果制作自定义整数类(如上所建议)不符合您对“简单方法”的定义,则您的问题的答案是,没有简单的方法可以实现您想要的功能。


0

我知道这是一篇旧帖子,但我认为它仍然对某些人有用。我使用这个来设置上下限:

bounded_value = max(min(your_value,upper_bound),lower_bound);

你可以在一个函数中使用它,就像这样:
float bounded_value(float x, float upper, float under){
    return max(min(x,upper),lower);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接