【问题标题】:Is there a good, performant unsigned BigInteger type for C#?C# 是否有一个好的、高性能的无符号 BigInteger 类型?
【发布时间】:2011-08-22 04:25:11
【问题描述】:

我熟悉 System.Numerics.BigInteger 类,但在我的应用程序中,我只处理正整数。负整数是一种错误情况,如果有 BigInteger 类型的无符号等价物,那就太好了,这样我就可以删除所有这些检查。有吗?

【问题讨论】:

  • @Splendor:我不认为这真的是被问到的......
  • 谢谢乔恩。我已经删除了我的 cmets。
  • 我不明白你为什么会说 (a) 负数是一个错误情况,而 (b) 你想创建一个无符号类型,那会做什么呢?如果您尝试分配负值,是否会引发异常?

标签: c# biginteger unsigned


【解决方案1】:

框架中不支持将BigInteger 声明为unsigned。但是,您可以创建一个静态方法来检查数字是否为负数。

public static void ValidateBigIntForUnsigned(BigInteger bigInteger)
{
   if(bigInteger.Sign < 0)
       throw new Exception("Only unsigned numbers are allowed!");
}

【讨论】:

【解决方案2】:

框架中什么都没有,没有。我会尝试将检查集中在尽可能小的公共 API 中,然后在其余时间将数据视为有效 - 就像您对 null 检查之类的事情一样。当然,如果您执行任何可能创建负值的操作(例如,从另一个中减去),您仍然需要小心。

您可以通过创建扩展方法使代码稍微整洁一些,例如

public static void ThrowIfNegative(this BigInteger value, string name)
{
    if (value.Sign < 0)
    {
        throw new ArgumentOutOfRangeException(name);
    }
}

...并像这样使用它:

input.ThrowIfNegative("input");

您可能会创建自己的 UBigInteger 结构,其中包含 BigInteger,并通过使用 BigInteger 实现和检查在不同值之间执行操作,但我怀疑这将是相当多的工作相对较少好处,并且如果您将它用于大量计算,可能会影响性能。

【讨论】:

    【解决方案3】:

    如果您只使用 BigInteger API 的一个相当小的子集,那么编写自己的包装类很容易,但很费力。这里有一些示例代码来证明它不需要那么大的操作:

    public struct UnsignedBigInteger
    {
        private BigInteger value;
        private UnsignedBigInteger(BigInteger n) { value = n; }
    
        public UnsignedBigInteger(uint n) { value = new BigInteger(n); }
        // ... other constructors ...
    
        public static UnsignedBigInteger operator+(UnsignedBigInteger lhs, UnsignedBigInteger rhs)
        {
            return new UnsignedBigInteger(lhs.value + rhs.value);
        }
        public static UnsignedBigInteger operator-(UnsignedBigInteger lhs, UnsignedBigInteger rhs)
        {
            var result = lhs.value - rhs.value;
            if (result < BigInteger.Zero) throw new InvalidOperationException("value out of range");
            return new UnsignedBigInteger(result);
        }
        // ... other operators ...
    }
    

    【讨论】:

      【解决方案4】:

      好吧,我们来看一个简单的例子

              uint a=1;
              uint b=2;
              uint c=a-b;
              Console.WriteLine(c);
      

      为您提供输出 4294967295 (=2^32-1)。

      但是,如果您有一个具有类似行为的未签名 BigInteger 怎么办?

              UBigInteger a(1);
              UBigInteger b(2);
              UBigInteger c=a-b;
              Console.WriteLine(c.ToString());
      

      那应该是什么?当然,根据您所写的内容,您可以假设在这种情况下您可能会遇到某种异常,但这种行为与int 不一致。更好地在您需要的地方引入

      【讨论】:

        【解决方案5】:

        如果负值存在这样的问题,是否有可能以某种方式消除它们,从而使不良数据(负值)甚至达不到您的逻辑?这将一起消除检查。你能发布一个简短的sn-p你在做什么吗?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-24
          • 2018-08-14
          • 1970-01-01
          • 2016-10-10
          • 2011-08-04
          • 2015-12-15
          相关资源
          最近更新 更多