是否有适用于 C# 的良好、高性能的无符号 BigInteger 类型
本文关键字:高性能 无符号 BigInteger 类型 适用于 是否 | 更新日期: 2023-09-27 17:56:11
>我熟悉System.Numerics.BigInteger类,但在我的应用程序中,我只处理正整数。负整数是一种错误情况,如果有一个 BigInteger 类型的无符号等效项,这样我就可以删除所有这些检查,那就太好了。存在吗?
框架中没有任何内容,没有。我会尝试将检查集中在尽可能小的公共 API 中,然后在其余时间将数据视为有效 - 就像您对空检查之类的事情一样。当然,如果您执行任何可能产生负值的操作(例如,从一个减去另一个),您仍然需要小心。
您可以通过创建扩展方法使代码稍微整洁一些,例如
public static void ThrowIfNegative(this BigInteger value, string name)
{
if (value.Sign < 0)
{
throw new ArgumentOutOfRangeException(name);
}
}
。并像这样使用它:
input.ThrowIfNegative("input");
您可以创建自己的包含BigInteger
的 UBigInteger
结构,并使用BigInteger
实现和检查在不同值之间执行操作,但我怀疑这将是相当多的工作,相对较少的好处,并且如果您将其用于大量计算,可能会对性能产生影响。
好吧,让我们看一个简单的例子
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
不一致。例如,最好在需要的地方引入<0 的检查,就像 Jon Skeet 建议的那样。
如果您只使用 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 ...
}
如果负值存在这样的问题,是否可以以某种方式消除它们,以便错误数据(负值)甚至无法到达您的逻辑?这将一起消除检查。你能发布一个你正在做的事情的简短片段吗?
框架中没有任何支持将BigInteger
声明为 unsigned
。但是,您可以创建一个静态方法来检查该数字是否为负数。
public static void ValidateBigIntForUnsigned(BigInteger bigInteger)
{
if(bigInteger.Sign < 0)
throw new Exception("Only unsigned numbers are allowed!");
}