C# BigInteger 的使用
总目录
前言
BigInteger 是 C# 提供的一种特殊数据类型,用于表示任意大小的整数。与传统的整数类型(如 int、long)相比,BigInteger 没有固定的大小限制,只受可用虚拟内存的限制,因此可以处理非常大的数值。本文将详细介绍 BigInteger 类的基本用法、常见操作以及一些实用技巧。
一、BigInteger 是什么?
1. 基本介绍
- BigInteger 表示任意大有符号整数。
- 继承:Object → ValueType → BigInteger
- 位于 System.Numerics 命名空间
与传统数值类型不同,BigInteger不会被预先固定的内存大小所束缚。它就像一个智能的存储空间,能够依据所表示数字的规模,动态地调整内存分配。这一特性使它如同拥有了无限容量的口袋,能够轻松处理各种大小的整数,无论是日常的小额交易金额,还是天文学中星系间的庞大距离数值。
2. 创建与初始化BigInteger
- 通过常量初始化
BigInteger num1 = 12345678901234567890;
- 通过构造函数创建
BigInteger bigInt1 = new BigInteger(987654321);
byte[] bytes = { 0x01, 0x02, 0x03, 0x04 };
bigInt1 = new BigInteger(bytes);
- 通过使用静态方法 Parse 或 TryParse 从字符串转换。
BigInteger bigInt2 = BigInteger.Parse("12345678901234567890");
- 从其他数值类型的隐式或显式转换。
int smallInt = 42;
BigInteger bigInt3 = smallInt; // 隐式转换
二、BigInteger 的优势与劣势
1. 优势
1)无限范围
由于 BigInteger 没有固定的大小,因此可以用来处理非常大的数字。
以计算阶乘为例,这是一个随着数字增大,普通整数类型迅速败下阵来的典型场景。普通的int或long类型,在面对较大数字的阶乘时,就像小水桶试图装下无尽的海水,很快就会溢出。而BigInteger则能轻松应对,如同一望无际的大海,容纳一切:
public static BigInteger Factorial(int n)
{
BigInteger result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
return result;
}
static void Main(string[] args)
{
BigInteger num1 = Program.Factorial(100);
Console.WriteLine(num1);
// 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
}
2)精确计算
在高精度计算场景中,BigInteger不会出现精度丢失的问题。这对于金融计算、科学计算等领域意义重大。例如,在计算高精度圆周率时,BigInteger能保证结果的准确性。
2. 劣势
1)性能上存在劣势
由于BigInteger需要动态分配内存,并且在计算过程中需要调动更多的计算资源,这就好比一辆大型货车,虽然载货能力强,但启动和行驶速度相对较慢。在进行简单的加法运算时,int类型就像轻巧的摩托车,能够迅速完成任务,而BigInteger则需要更多的时间和资源来完成相同的操作:
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
int a = 1;
int b = 2;
int result = a + b;
}
stopwatch.Stop();
Console.WriteLine($"int加法运算耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
stopwatch.Restart();
for (int i = 0; i < 1000000; i++)
{
BigInteger a = 1;
BigInteger b = 2;
BigInteger result = a + b;
}
stopwatch.Stop();
Console.WriteLine($"BigInteger加法运算耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
}
输出结果:
int加法运算耗时: 2 毫秒
BigInteger加法运算耗时: 26 毫秒
2)存在内存不足的问题
随着所表示数字的不断增大,BigInteger占用的内存也会如气球般膨胀。在处理大量BigInteger数据时,就像在一个有限空间里不断堆积大型物品,很可能会导致内存不足的问题。例如,当我们创建一个包含大量超大BigInteger的列表时:
static void Main(string[] args)
{
List<BigInteger> bigIntegerList = new List<BigInteger>();
for (int i = 0; i < 10000; i++)
{
bigIntegerList.Add(BigInteger.Parse(new string('9', 100000)));
}
}
这段代码试图创建一个包含一万个长度为100000的全9数字的BigInteger列表,在运行过程中,很可能会因为内存占用过大而导致程序崩溃。
三、常用运算
BigInteger 支持常规的算术运算符(+、-、*、/、%),以及位移运算符(<<, >>)和逻辑运算符(&, |, ^)。此外,还支持比较运算符(==, !=, <, >, <=, >=)。
1. 算数运算
BigInteger a = 123;
BigInteger b = 456;
BigInteger sum = a + b;
BigInteger difference = a - b;
BigInteger product = a * b;
BigInteger quotient = a / b;
BigInteger remainder = a % b;
除以上直接通过运算符去计算之外,还可以使用由BingInteger 提供的静态方法
public static BigInteger Add(BigInteger left, BigInteger right)
{
return left + right;
}
public static BigInteger Subtract(BigInteger left, BigInteger right)
{
return left - right;
}
public static BigInteger Multiply(BigInteger left, BigInteger right)
{
return left * right;
}
public static BigInteger Divide(BigInteger dividend, BigInteger divisor)
{
return dividend / divisor;
}
public static BigInteger Remainder(BigInteger dividend, BigInteger divisor)
{
return dividend % divisor;
}
static void Main(string[] args)
{
BigInteger bigInt1 = new BigInteger(987654321);
BigInteger bigInt2 = BigInteger.Parse("12345678901234567890");
BigInteger sum = BigInteger.Add(bigInt1, bigInt2);
BigInteger difference = BigInteger.Subtract(bigInt1, bigInt2);
BigInteger product = BigInteger.Multiply(bigInt1, bigInt2);
BigInteger quotient = BigInteger.Divide(bigInt1, bigInt2);
}
2. 比较运算
BigInteger x = 100;
BigInteger y = 200;
bool isLessThan = x < y;
bool isGreaterThan = x > y;
bool isEqual = x == y;
3. 位运算
BigInteger m = 5; // 二进制为 101
BigInteger n = 3; // 二进制为 011
BigInteger andResult = m & n; // 按位与,结果为 001
BigInteger orResult = m | n; // 按位或,结果为 111
BigInteger xorResult = m ^ n; // 按位异或,结果为 110
4. 其他常用方法
public static BigInteger Max(BigInteger left, BigInteger right)
{
if (left.CompareTo(right) < 0)
return right;
return left;
}
public static BigInteger Min(BigInteger left, BigInteger right)
{
if (left.CompareTo(right) <= 0)
return left;
return right;
}
更多详情可见:System.Numerics.BigInteger 结构、BigInteger 结构
四、数据转换
1. 转换为数值类型
BigInteger bigInt = 123;
int normalInt = (int)bigInt;
但需要格外注意的是,如果BigInteger的值超出了目标类型的范围,就像试图将一个大箱子塞进一个小盒子,转换会导致数据丢失或引发异常。比如:
static void Main(string[] args)
{
BigInteger tooBigInt = 2147483648; // 超出int范围
try
{
int normalInt = (int)tooBigInt;
}
catch (OverflowException ex)
{
Console.WriteLine($"转换时发生溢出异常: {ex.Message}");
}
}
2. 转换为字符串
BigInteger num = 12345678901234567890;
string numStr = num.ToString();
五、应用场景
1. 密码学领域的坚固堡垒
在加密算法的神秘世界里,BigInteger就像一位忠诚的卫士,守护着信息的安全。加密算法常常需要处理极大的质数,这些质数就像密码锁的复杂密码,只有通过BigInteger的强大能力,才能准确地生成和处理。例如,在RSA加密算法中,需要使用极大的整数来进行加密和解密操作,BigInteger能够完美地满足这一需求,确保加密的安全性如同坚固的堡垒:
// RSA加密算法中使用BigInteger的简单示例
BigInteger p = BigInteger.Parse("123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200");
BigInteger q = BigInteger.Parse("201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400");
// 后续进行复杂的RSA计算步骤
2. 科学计算领域的得力助手
在天文学、物理学等科学领域的浩瀚宇宙中,BigInteger是科学家们的得力助手。这些领域常常涉及极大或极小的数值计算,如计算星系之间的距离,那是一个遥远到难以想象的数字,普通数值类型望尘莫及;还有微观粒子的质量,微小到几乎无法用常规方式表示。而BigInteger凭借其强大的能力,能够精准地进行这些计算,为科学研究提供坚实的支持:
// 简单模拟计算星系间距离(实际数据和计算会更复杂)
BigInteger distanceUnit = BigInteger.Parse("100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
六. 注意事项
- 在进行涉及 BigInteger 的除法操作时,如果除数为零,会抛出 DivideByZeroException。
- 当将 BigInteger 转换为较小的数值类型时,如果超出目标类型的范围,则会引发 OverflowException,除非启用了检查溢出的编译器选项。
- BigInteger 是不可变的;每次执行修改操作都会生成新的 BigInteger 实例。
- 精度问题
- 虽然BigInteger在整数运算中保证精度,但在与浮点数相关的转换或运算中,可能会出现精度丢失。例如,将BigInteger转换为float或double时,由于浮点数的表示精度有限,可能无法精确表示BigInteger的值。
- 因此,在涉及精度要求极高的场景,尤其是从BigInteger转换为浮点数类型时,需要谨慎处理。
结语
回到目录页:C# 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。
参考资料:
System.Numerics.BigInteger 结构
BigInteger 结构
C# BigInteger 处理超大整型数字