【问题标题】:How to represent integer infinity?如何表示整数无穷大?
【发布时间】:2014-01-23 15:12:54
【问题描述】:

我需要一种方法来表示一个可以是无限的整数。我不想使用浮点类型(double.PositiveInfinity),因为数字永远不能是小数,这可能会使 API 混乱。最好的方法是什么?

编辑:我还没有看到的一个想法是使用 int? null 代表无穷大。有什么好的理由不这样做吗?

【问题讨论】:

  • 制作一个带有无穷大标志的包装器类型。
  • 并且该包装器类型在内部只能容纳一个int。按照惯例,int.MaxValue 代表的不是自己,而是无限。
  • 创建一个Nullable<int> 并将null 的值视为无限。
  • 减去1会发生什么? OutOfMemoryException?
  • @MrLister,double.MaxValue 和无穷大之间有很多整数值。无限量的事实。

标签: c# infinity


【解决方案1】:

如果您不需要完整范围的整数值,可以使用int.MaxValueint.MinValue 常量来表示无穷大。

但是,如果需要完整的值范围,我建议要么创建一个包装类,要么直接使用双精度值。

【讨论】:

  • 那不会保留减法。
  • 即将在评论中提供相同的想法。顺便说一句,他需要一个包装器,因为1 / 0 = DivideByZeroException =D
  • @SLaks 你不应该尝试从无穷大中加减。
  • @SLaks OP 没有指定任何关于执行算术的内容,而是在 API 中表示无穷大。
  • 为了使这项工作 - 或任何无限概念,就此而言 - 您必须实现检查无限操作数并采取相应行动的隐式运算符。
【解决方案2】:

一个示例部分实现沿 SLaks 和其他的 cmets 行(欢迎反馈):

用法:

int x = 4;
iint pi = iint.PositiveInfinity;
iint ni = iint.NegativeInfinity;

Assert.IsTrue(x + pi == iint.PositiveInfinity);
Assert.IsTrue(pi + 1 == iint.PositiveInfinity);
Assert.IsTrue(pi + (-ni) == iint.PositiveInfinity);
Assert.IsTrue((int)((iint)5) == 5);

实施:

public struct iint
{
    private readonly int _int;

    public iint(int value) 
    {
        if(value  == int.MaxValue || value == int.MinValue)
            throw new InvalidOperationException("min/max value reserved in iint");
        _int = value;
    }

    public static explicit operator int(iint @this)
    {
        if(@this._int == int.MaxValue || @this._int == int.MinValue)
            throw new InvalidOperationException("cannot implicit convert infinite iint to int");

        return @this._int;
    }

    public static implicit operator iint(int other)
    {
        if(other == int.MaxValue || other == int.MinValue)
            throw new InvalidOperationException("cannot implicit convert max-value into to iint");
        return new iint(other);
    }

    public bool IsPositiveInfinity {get { return _int == int.MaxValue; } }

    public bool IsNegativeInfinity { get { return _int == int.MinValue; } }

    private iint(bool positive)
    {
        if (positive)
            _int = int.MaxValue;
        else
            _int = int.MinValue;
    }

    public static readonly iint PositiveInfinity = new iint(true);

    public static readonly iint NegativeInfinity = new iint(false);

    public static bool operator ==(iint a, iint b)
    {
        return a._int == b._int;
    }

    public static bool operator !=(iint a, iint b)
    {
        return a._int != b._int;
    }

    public static iint operator +(iint a, iint b)
    {
        if (a.IsPositiveInfinity && b.IsNegativeInfinity)
            throw new InvalidOperationException();
        if (b.IsPositiveInfinity && a.IsNegativeInfinity)
            throw new InvalidOperationException();
        if (a.IsPositiveInfinity)
            return PositiveInfinity;
        if (a.IsNegativeInfinity)
            return NegativeInfinity;
        if (b.IsPositiveInfinity)
            return PositiveInfinity;
        if (b.IsNegativeInfinity)
            return NegativeInfinity;

        return a._int + b._int;
    }

    public static iint operator -(iint a, iint b)
    {
        if (a.IsPositiveInfinity && b.IsPositiveInfinity)
            throw new InvalidOperationException();
        if (a.IsNegativeInfinity && b.IsNegativeInfinity)
            throw new InvalidOperationException();
        if (a.IsPositiveInfinity)
            return PositiveInfinity;
        if (a.IsNegativeInfinity)
            return NegativeInfinity;
        if (b.IsPositiveInfinity)
            return NegativeInfinity;
        if (b.IsNegativeInfinity)
            return PositiveInfinity;

        return a._int - b._int;
    }

    public static iint operator -(iint a)
    {
        if (a.IsNegativeInfinity)
            return PositiveInfinity;
        if (a.IsPositiveInfinity)
            return NegativeInfinity;

        return -a;
    }

    /* etc... */
    /* other operators here */
}

【讨论】:

  • 赞成。当您发布此内容时,我正在编写非常相似的代码(请参阅我的答案)。
  • 我看到的一个问题(我想我的帖子中也有问题!)是说 2,000,000,000 和 2,000,000,000 的总和将“环绕”为否定结果。在这种情况下,我希望PositiveInfinity
【解决方案3】:

您的 API 可以使用约定,int.MaxValue 表示正无穷值,int.MinValue - 负无穷。

但是您仍然需要在某个地方记录它,并且您可能需要对无限整数进行一些操作:

 /// <summary>
/// Making int infinity
/// ...
/// </summary>
public static class IntExtension
{

    public const int PositiveInfinity = int.MaxValue;

    public const int NegativeInfinity = int.MinValue;

    public static bool IsPositiveInfinity(this int x)
    {
        return x == PositiveInfinity;
    }

    public static bool IsNegativeInfinity(this int x)
    {
        return x == NegativeInfinity;
    }

    public static int Operation(this int x, int y)
    {
        // ...

        return PositiveInfinity;
    }
}

【讨论】:

【解决方案4】:

另一个部分实现(我看到 Jack 更快):

struct InfinityInt
{
  readonly int Value;

  InfinityInt(int value, bool allowInfinities)
  {
    if (!allowInfinities && (value == int.MinValue || value == int.MaxValue))
      throw new ArgumentOutOfRangeException("value");
    Value = value;
  }

  public InfinityInt(int value)
    : this(value, false)
  {
  }

  public static InfinityInt PositiveInfinity = new InfinityInt(int.MaxValue, true);

  public static InfinityInt NegativeInfinity = new InfinityInt(int.MinValue, true);

  public bool IsAnInfinity
  {
    get { return Value == int.MaxValue || Value == int.MinValue; }
  }

  public override string ToString()
  {
    if (Value == int.MinValue)
      return double.NegativeInfinity.ToString();
    if (Value == int.MaxValue)
      return double.PositiveInfinity.ToString();

    return Value.ToString();
  }

  public static explicit operator int(InfinityInt ii)
  {
    if (ii.IsAnInfinity)
      throw new OverflowException();
    return ii.Value;
  }
  public static explicit operator double(InfinityInt ii)
  {
    if (ii.Value == int.MinValue)
      return double.NegativeInfinity;
    if (ii.Value == int.MaxValue)
      return double.PositiveInfinity;

    return ii.Value;
  }
  public static explicit operator InfinityInt(int i)
  {
    return new InfinityInt(i); // can throw
  }
  public static explicit operator InfinityInt(double d)
  {
    if (double.IsNaN(d))
      throw new ArgumentException("NaN not supported", "d");
    if (d >= int.MaxValue)
      return PositiveInfinity;
    if (d <= int.MinValue)
      return NegativeInfinity;

    return new InfinityInt((int)d);
  }

  static InfinityInt FromLongSafely(long x)
  {
    if (x >= int.MaxValue)
      return PositiveInfinity;
    if (x <= int.MinValue)
      return NegativeInfinity;

    return new InfinityInt((int)x);
  }

  public static InfinityInt operator +(InfinityInt a, InfinityInt b)
  {
    if (a.IsAnInfinity || b.IsAnInfinity)
    {
      if (!b.IsAnInfinity)
        return a;
      if (!a.IsAnInfinity)
        return b;
      if (a.Value == b.Value)
        return a;

      throw new ArithmeticException("Undefined");
    }
    return FromLongSafely((long)a.Value + (long)b.Value);
  }
  public static InfinityInt operator *(InfinityInt a, InfinityInt b)
  {
    if (a.IsAnInfinity || b.IsAnInfinity)
    {
      if (a.Value == 0 || b.Value == 0)
        throw new ArithmeticException("Undefined");

      return (a.Value > 0) == (b.Value > 0) ? PositiveInfinity : NegativeInfinity;
    }
    return FromLongSafely((long)a.Value * (long)b.Value);
  }

  // and so on, and so on
}

【讨论】:

    【解决方案5】:

    C# 有一个类型,BigInteger 类是无限大小的

    http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx

    如果您希望该类具有无穷大的表示形式——然后将 BigInteger 包装在一个为其提供无穷大标志的类中。

    您必须重新定义所有标准运算符和转换才能使其正常工作。

    究竟如何对无穷大工作进行操作取决于您的领域。

    (例如,在某些形式的数学中,您想要 2 x infinity = infinity,而在某些形式中您不想要)。

    如何实现细节实际上取决于您的域问题,并且从您的问题中不清楚。

    【讨论】:

    • 不,BigInteger 不能保存特定值“infinite”。
    • BigInteger 可以容纳int 的整个有效范围加上额外的。其中一些额外的可能是无限的(例如,任何高于int.MaxValue + 1are Infinite 的值)。在计算+Infinity - 2 = int.MaxValue - 1 时仍应注意使用这种无穷大,但它仍应以某种方式保持无穷大。
    • 在 CodePlex、CodeProject 等上有各种各样的 BigInteger 类,其中一个来自 MS in System.Numerics。 MS 没有 Infinity 标志。我不知道其他人的质量如何,但鉴于他们中的大多数人都对数字的字符串表示进行操作,他们不会很快。
    • @JeppeStigNielsen,无限是一个特定的值吗?
    • @Sinatr - 我的意思是这些函数需要添加到你的类中以支持域
    猜你喜欢
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 2022-08-12
    • 2014-12-28
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多