System.Numerics.BigInteger 结构
本文提供了此 API 参考文档的补充说明。
该 BigInteger 类型是一个不可变类型,表示一个任意较大的整数,其理论上的值没有上限或下限。 类型的成员BigInteger与其他整型类型(Byte即、、Int16Int32、SByteInt64、UInt16、和UInt32UInt64类型)的成员紧密平行。 此类型不同于 .NET 中的其他整型类型,这些类型具有由其 MinValue
和 MaxValue
属性指示的范围。
注意
BigInteger由于类型是不可变的(请参阅可变性),并且因为它没有上限或下限,因此对于导致值增长过大的任何操作,可能会引发一个OutOfMemoryExceptionBigInteger值。
实例化 BigInteger 对象
可以通过多种方式实例化 BigInteger 对象:
可以使用
new
关键字 (keyword),并将任何整型或浮点值作为构造函数的参数BigInteger提供。 (在将浮点值分配给 .BigInteger)以下示例演示如何使用new
关键字 (keyword)实例化BigInteger值。BigInteger bigIntFromDouble = new BigInteger(179032.6541); Console.WriteLine(bigIntFromDouble); BigInteger bigIntFromInt64 = new BigInteger(934157136952); Console.WriteLine(bigIntFromInt64); // The example displays the following output: // 179032 // 934157136952
Dim bigIntFromDouble As New BigInteger(179032.6541) Console.WriteLine(bigIntFromDouble) Dim bigIntFromInt64 As New BigInteger(934157136952) Console.WriteLine(bigIntFromInt64) ' The example displays the following output: ' 179032 ' 934157136952
可以声明变量 BigInteger 并将其赋值,就像任何数值类型一样,只要该值是整型类型。 以下示例使用赋值 BigInteger 从 . Int64.
long longValue = 6315489358112; BigInteger assignedFromLong = longValue; Console.WriteLine(assignedFromLong); // The example displays the following output: // 6315489358112
Dim longValue As Long = 6315489358112 Dim assignedFromLong As BigInteger = longValue Console.WriteLine(assignedFromLong) ' The example displays the following output: ' 6315489358112
如果将值强制转换或首先转换,则可以将小数或浮点值 BigInteger 分配给对象。 以下示例显式强制转换(以 C#为单位)或将(在 Visual Basic 中)和 Double 值 Decimal 转换为值 BigInteger。
BigInteger assignedFromDouble = (BigInteger) 179032.6541; Console.WriteLine(assignedFromDouble); BigInteger assignedFromDecimal = (BigInteger) 64312.65m; Console.WriteLine(assignedFromDecimal); // The example displays the following output: // 179032 // 64312
Dim assignedFromDouble As BigInteger = CType(179032.6541, BigInteger) Console.WriteLine(assignedFromDouble) Dim assignedFromDecimal As BigInteger = CType(64312.65D, BigInteger) Console.WriteLine(assignedFromDecimal) ' The example displays the following output: ' 179032 ' 64312
这些方法使你能够实例化 BigInteger 其值仅在现有数值类型之一范围内的对象。 可以实例化一个 BigInteger 对象,其值可以通过以下三种方式之一超过现有数值类型的范围:
可以使用
new
关键字 (keyword)并向构造函数提供任何大小的BigInteger.BigInteger字节数组。 例如:byte[] byteArray = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; BigInteger newBigInt = new BigInteger(byteArray); Console.WriteLine("The value of newBigInt is {0} (or 0x{0:x}).", newBigInt); // The example displays the following output: // The value of newBigInt is 4759477275222530853130 (or 0x102030405060708090a).
Dim byteArray() As Byte = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} Dim newBigInt As New BigInteger(byteArray) Console.WriteLine("The value of newBigInt is {0} (or 0x{0:x}).", newBigInt) ' The example displays the following output: ' The value of newBigInt is 4759477275222530853130 (or 0x102030405060708090a).
可以调用 Parse 或 TryParse 方法将数字的字符串表示形式转换为 a BigInteger. 例如:
string positiveString = "91389681247993671255432112000000"; string negativeString = "-90315837410896312071002088037140000"; BigInteger posBigInt = 0; BigInteger negBigInt = 0; try { posBigInt = BigInteger.Parse(positiveString); Console.WriteLine(posBigInt); } catch (FormatException) { Console.WriteLine("Unable to convert the string '{0}' to a BigInteger value.", positiveString); } if (BigInteger.TryParse(negativeString, out negBigInt)) Console.WriteLine(negBigInt); else Console.WriteLine("Unable to convert the string '{0}' to a BigInteger value.", negativeString); // The example displays the following output: // 9.1389681247993671255432112E+31 // -9.0315837410896312071002088037E+34
Dim positiveString As String = "91389681247993671255432112000000" Dim negativeString As String = "-90315837410896312071002088037140000" Dim posBigInt As BigInteger = 0 Dim negBigInt As BigInteger = 0 Try posBigInt = BigInteger.Parse(positiveString) Console.WriteLine(posBigInt) Catch e As FormatException Console.WriteLine("Unable to convert the string '{0}' to a BigInteger value.", positiveString) End Try If BigInteger.TryParse(negativeString, negBigInt) Then Console.WriteLine(negBigInt) Else Console.WriteLine("Unable to convert the string '{0}' to a BigInteger value.", negativeString) End If ' The example displays the following output: ' 9.1389681247993671255432112E+31 ' -9.0315837410896312071002088037E+34
可以调用在
static
Shared
Visual Basic BigInteger 中对数值表达式执行某些操作并返回计算BigInteger结果的方法。 以下示例通过分块 UInt64.MaxValue 并将结果分配给 a BigInteger.BigInteger number = BigInteger.Pow(UInt64.MaxValue, 3); Console.WriteLine(number); // The example displays the following output: // 6277101735386680762814942322444851025767571854389858533375
Dim number As BigInteger = BigInteger.Pow(UInt64.MaxValue, 3) Console.WriteLine(number) ' The example displays the following output: ' 6277101735386680762814942322444851025767571854389858533375
未初始化的值 BigInteger 为 Zero.
对 BigInteger 值执行操作
可以使用 BigInteger 实例,就像使用任何其他整型类型一样。 BigInteger 重载标准数值运算符,使你能够执行基本的数学运算,例如加法、减法、除法、乘法和一元求反。 还可以使用标准数值运算符来比较两 BigInteger 个值。 与其他整型类型一样, BigInteger 还支持按位 And
、 Or
左 XOr
移和右移运算符。 对于不支持自定义运算符的语言,该 BigInteger 结构还提供用于执行数学运算的等效方法。 Add其中包括、Divide、Multiply、Negate和Subtract几个其他项。
结构中的 BigInteger 许多成员直接对应于其他整型类型的成员。 此外, BigInteger 添加如下成员:
Sign,该值返回一个值,该值指示值的 BigInteger 符号。
Abs,该值返回值的 BigInteger 绝对值。
DivRem,返回除法运算的商和余数。
GreatestCommonDivisor,返回两 BigInteger 个值的最大常见除数。
其中许多附加成员对应于类的成员,该成员 Math 提供使用基元数值类型的功能。
可变性
以下示例实例化一个 BigInteger 对象,然后将其值递增一个。
BigInteger number = BigInteger.Multiply(Int64.MaxValue, 3);
number++;
Console.WriteLine(number);
Dim number As BigInteger = BigInteger.Multiply(Int64.MaxValue, 3)
number += 1
Console.WriteLine(number)
尽管此示例似乎修改现有对象的值,但情况并非如此。 BigInteger 对象是不可变的,这意味着在内部,公共语言运行时实际上会创建一个新 BigInteger 对象,并为其分配一个大于其先前值的值。 然后,此新对象将返回到调用方。
注意
.NET 中的其他数值类型也是不可变的。 但是,由于 BigInteger 该类型没有上限或下限,因此其值可能会增长非常大,并且会对性能产生可衡量的影响。
尽管此过程对调用方是透明的,但它确实会产生性能损失。 在某些情况下,尤其是在对非常大 BigInteger 的值循环中执行重复操作时,性能损失可能会很大。 例如,在下面的示例中,每次操作成功时,都会重复执行一个操作,并且每次操作成功时,都会递增一个 BigInteger 值。
BigInteger number = Int64.MaxValue ^ 5;
int repetitions = 1000000;
// Perform some repetitive operation 1 million times.
for (int ctr = 0; ctr <= repetitions; ctr++)
{
// Perform some operation. If it fails, exit the loop.
if (!SomeOperationSucceeds()) break;
// The following code executes if the operation succeeds.
number++;
}
Dim number As BigInteger = Int64.MaxValue ^ 5
Dim repetitions As Integer = 1000000
' Perform some repetitive operation 1 million times.
For ctr As Integer = 0 To repetitions
' Perform some operation. If it fails, exit the loop.
If Not SomeOperationSucceeds() Then Exit For
' The following code executes if the operation succeeds.
number += 1
Next
在这种情况下,可以通过对变量执行所有中间赋值 Int32 来提高性能。 然后,变量的最终值可以在循环退出时分配给 BigInteger 对象。 下面的示例进行了这方面的演示。
BigInteger number = Int64.MaxValue ^ 5;
int repetitions = 1000000;
int actualRepetitions = 0;
// Perform some repetitive operation 1 million times.
for (int ctr = 0; ctr <= repetitions; ctr++)
{
// Perform some operation. If it fails, exit the loop.
if (!SomeOperationSucceeds()) break;
// The following code executes if the operation succeeds.
actualRepetitions++;
}
number += actualRepetitions;
Dim number As BigInteger = Int64.MaxValue ^ 5
Dim repetitions As Integer = 1000000
Dim actualRepetitions As Integer = 0
' Perform some repetitive operation 1 million times.
For ctr As Integer = 0 To repetitions
' Perform some operation. If it fails, exit the loop.
If Not SomeOperationSucceeds() Then Exit For
' The following code executes if the operation succeeds.
actualRepetitions += 1
Next
number += actualRepetitions
字节数组和十六进制字符串
如果将值转换为 BigInteger 字节数组,或者将字节数组转换为 BigInteger 值,则必须考虑字节的顺序。 该 BigInteger 结构要求字节数组中的单个字节以小字节顺序显示(也就是说,该值的下序字节位于高阶字节之前)。 可以通过调用ToByteArray该方法,然后将生成的字节数组传递给BigInteger(Byte[])构造函数来往返BigInteger值,如以下示例所示。
BigInteger number = BigInteger.Pow(Int64.MaxValue, 2);
Console.WriteLine(number);
// Write the BigInteger value to a byte array.
byte[] bytes = number.ToByteArray();
// Display the byte array.
foreach (byte byteValue in bytes)
Console.Write("0x{0:X2} ", byteValue);
Console.WriteLine();
// Restore the BigInteger value from a Byte array.
BigInteger newNumber = new BigInteger(bytes);
Console.WriteLine(newNumber);
// The example displays the following output:
// 8.5070591730234615847396907784E+37
// 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x3F
//
// 8.5070591730234615847396907784E+37
Dim number As BigInteger = BigInteger.Pow(Int64.MaxValue, 2)
Console.WriteLine(number)
' Write the BigInteger value to a byte array.
Dim bytes() As Byte = number.ToByteArray()
' Display the byte array.
For Each byteValue As Byte In bytes
Console.Write("0x{0:X2} ", byteValue)
Next
Console.WriteLine()
' Restore the BigInteger value from a Byte array.
Dim newNumber As BigInteger = New BigInteger(bytes)
Console.WriteLine(newNumber)
' The example displays the following output:
' 8.5070591730234615847396907784E+37
' 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x3F
'
' 8.5070591730234615847396907784E+37
若要实例化 BigInteger 表示其他一些整型类型的值的字节数组中的值,可以将整型值 BitConverter.GetBytes 传递给方法,然后将生成的字节数组传递给 BigInteger(Byte[]) 构造函数。 以下示例从表示值的字节数组实例化 BigInteger 一个 Int16 值。
short originalValue = 30000;
Console.WriteLine(originalValue);
// Convert the Int16 value to a byte array.
byte[] bytes = BitConverter.GetBytes(originalValue);
// Display the byte array.
foreach (byte byteValue in bytes)
Console.Write("0x{0} ", byteValue.ToString("X2"));
Console.WriteLine();
// Pass byte array to the BigInteger constructor.
BigInteger number = new BigInteger(bytes);
Console.WriteLine(number);
// The example displays the following output:
// 30000
// 0x30 0x75
// 30000
Dim originalValue As Short = 30000
Console.WriteLine(originalValue)
' Convert the Int16 value to a byte array.
Dim bytes() As Byte = BitConverter.GetBytes(originalValue)
' Display the byte array.
For Each byteValue As Byte In bytes
Console.Write("0x{0} ", byteValue.ToString("X2"))
Next
Console.WriteLine()
' Pass byte array to the BigInteger constructor.
Dim number As BigInteger = New BigInteger(bytes)
Console.WriteLine(number)
' The example displays the following output:
' 30000
' 0x30 0x75
' 30000
该 BigInteger 结构假定负值通过使用两的补数表示形式来存储。 BigInteger由于结构表示没有固定长度的数值,BigInteger(Byte[])因此构造函数始终将数组中最后一个字节的最有效位解释为符号位。 为了防止 BigInteger(Byte[]) 构造函数混淆负值的补数表示形式与正值的符号和数量级表示形式,通常设置字节数组中最后一个字节的最有效位的正值应包含值为 0 的其他字节。 例如,0xC0 0xBD 0xF0 0xFF是 -1,000,000 或 4,293,967,296 的小数十六进制表示形式。 由于此数组中最后一个字节的最有效位处于打开的状态,因此字节数组的值将由构造函数解释 BigInteger(Byte[]) 为 -1,000,000。 若要实例化 BigInteger 其值为正的字节数组,必须将其元素0xC0 0xBD 0xF0 0xFF 0x00的字节数组传递给构造函数。 下面的示例对此进行了演示。
int negativeNumber = -1000000;
uint positiveNumber = 4293967296;
byte[] negativeBytes = BitConverter.GetBytes(negativeNumber);
BigInteger negativeBigInt = new BigInteger(negativeBytes);
Console.WriteLine(negativeBigInt.ToString("N0"));
byte[] tempPosBytes = BitConverter.GetBytes(positiveNumber);
byte[] positiveBytes = new byte[tempPosBytes.Length + 1];
Array.Copy(tempPosBytes, positiveBytes, tempPosBytes.Length);
BigInteger positiveBigInt = new BigInteger(positiveBytes);
Console.WriteLine(positiveBigInt.ToString("N0"));
// The example displays the following output:
// -1,000,000
// 4,293,967,296
Dim negativeNumber As Integer = -1000000
Dim positiveNumber As UInteger = 4293967296
Dim negativeBytes() As Byte = BitConverter.GetBytes(negativeNumber)
Dim negativeBigInt As New BigInteger(negativeBytes)
Console.WriteLine(negativeBigInt.ToString("N0"))
Dim tempPosBytes() As Byte = BitConverter.GetBytes(positiveNumber)
Dim positiveBytes(tempposBytes.Length) As Byte
Array.Copy(tempPosBytes, positiveBytes, tempPosBytes.Length)
Dim positiveBigInt As New BigInteger(positiveBytes)
Console.WriteLine(positiveBigInt.ToString("N0"))
' The example displays the following output:
' -1,000,000
' 4,293,967,296
由 ToByteArray 正值方法创建的字节数组包括此额外的零值字节。 因此,结构 BigInteger 可以通过向其分配这些值,然后从字节数组还原它们,从而成功往返值,如以下示例所示。
BigInteger positiveValue = 15777216;
BigInteger negativeValue = -1000000;
Console.WriteLine("Positive value: " + positiveValue.ToString("N0"));
byte[] bytes = positiveValue.ToByteArray();
foreach (byte byteValue in bytes)
Console.Write("{0:X2} ", byteValue);
Console.WriteLine();
positiveValue = new BigInteger(bytes);
Console.WriteLine("Restored positive value: " + positiveValue.ToString("N0"));
Console.WriteLine();
Console.WriteLine("Negative value: " + negativeValue.ToString("N0"));
bytes = negativeValue.ToByteArray();
foreach (byte byteValue in bytes)
Console.Write("{0:X2} ", byteValue);
Console.WriteLine();
negativeValue = new BigInteger(bytes);
Console.WriteLine("Restored negative value: " + negativeValue.ToString("N0"));
// The example displays the following output:
// Positive value: 15,777,216
// C0 BD F0 00
// Restored positive value: 15,777,216
//
// Negative value: -1,000,000
// C0 BD F0
// Restored negative value: -1,000,000
Dim positiveValue As BigInteger = 15777216
Dim negativeValue As BigInteger = -1000000
Console.WriteLine("Positive value: " + positiveValue.ToString("N0"))
Dim bytes() As Byte = positiveValue.ToByteArray()
For Each byteValue As Byte In bytes
Console.Write("{0:X2} ", byteValue)
Next
Console.WriteLine()
positiveValue = New BigInteger(bytes)
Console.WriteLine("Restored positive value: " + positiveValue.ToString("N0"))
Console.WriteLine()
Console.WriteLIne("Negative value: " + negativeValue.ToString("N0"))
bytes = negativeValue.ToByteArray()
For Each byteValue As Byte In bytes
Console.Write("{0:X2} ", byteValue)
Next
Console.WriteLine()
negativeValue = New BigInteger(bytes)
Console.WriteLine("Restored negative value: " + negativeValue.ToString("N0"))
' The example displays the following output:
' Positive value: 15,777,216
' C0 BD F0 00
' Restored positive value: 15,777,216
'
' Negative value: -1,000,000
' C0 BD F0
' Restored negative value: -1,000,000
但是,可能需要将此额外的零值字节添加到开发人员动态创建的字节数组,或者由将无符号整数转换为字节数组的方法返回的字节数组(例如 BitConverter.GetBytes(UInt16), BitConverter.GetBytes(UInt32)和 BitConverter.GetBytes(UInt64))。
分析十六进制字符串时,和BigInteger.Parse(String, NumberStyles)BigInteger.Parse(String, NumberStyles, IFormatProvider)方法假定如果设置了字符串中第一个字节的最有效位,或者字符串的第一个十六进制数字表示字节值的低四位,则使用两个的补补表示形式表示值。 例如,“FF01”和“F01”都表示十进制值 -255。 若要将正值与负值区分开来,正值应包括前导零。 方法的相关重载 ToString 在传递“X”格式字符串时,为正值将前导零添加到返回的十六进制字符串。 这样就可以使用ToString和Parse方法进行往返BigInteger值,如以下示例所示。
BigInteger negativeNumber = -1000000;
BigInteger positiveNumber = 15777216;
string negativeHex = negativeNumber.ToString("X");
string positiveHex = positiveNumber.ToString("X");
BigInteger negativeNumber2, positiveNumber2;
negativeNumber2 = BigInteger.Parse(negativeHex,
NumberStyles.HexNumber);
positiveNumber2 = BigInteger.Parse(positiveHex,
NumberStyles.HexNumber);
Console.WriteLine("Converted {0:N0} to {1} back to {2:N0}.",
negativeNumber, negativeHex, negativeNumber2);
Console.WriteLine("Converted {0:N0} to {1} back to {2:N0}.",
positiveNumber, positiveHex, positiveNumber2);
// The example displays the following output:
// Converted -1,000,000 to F0BDC0 back to -1,000,000.
// Converted 15,777,216 to 0F0BDC0 back to 15,777,216.
Dim negativeNumber As BigInteger = -1000000
Dim positiveNumber As BigInteger = 15777216
Dim negativeHex As String = negativeNumber.ToString("X")
Dim positiveHex As string = positiveNumber.ToString("X")
Dim negativeNumber2, positiveNumber2 As BigInteger
negativeNumber2 = BigInteger.Parse(negativeHex,
NumberStyles.HexNumber)
positiveNumber2 = BigInteger.Parse(positiveHex,
NumberStyles.HexNumber)
Console.WriteLine("Converted {0:N0} to {1} back to {2:N0}.",
negativeNumber, negativeHex, negativeNumber2)
Console.WriteLine("Converted {0:N0} to {1} back to {2:N0}.",
positiveNumber, positiveHex, positiveNumber2)
' The example displays the following output:
' Converted -1,000,000 to F0BDC0 back to -1,000,000.
' Converted 15,777,216 to 0F0BDC0 back to 15,777,216.
但是,通过调用ToString
其他整型类型的方法或包含toBase
参数的方法的重载ToString创建的十六进制字符串并不指示从中派生十六进制字符串的值或源数据类型的符号。 成功实例化 BigInteger 此类字符串中的值需要一些额外的逻辑。 以下示例提供了一个可能的实现。
using System;
using System.Globalization;
using System.Numerics;
public struct HexValue
{
public int Sign;
public string Value;
}
public class ByteHexExample2
{
public static void Main()
{
uint positiveNumber = 4039543321;
int negativeNumber = -255423975;
// Convert the numbers to hex strings.
HexValue hexValue1, hexValue2;
hexValue1.Value = positiveNumber.ToString("X");
hexValue1.Sign = Math.Sign(positiveNumber);
hexValue2.Value = Convert.ToString(negativeNumber, 16);
hexValue2.Sign = Math.Sign(negativeNumber);
// Round-trip the hexadecimal values to BigInteger values.
string hexString;
BigInteger positiveBigInt, negativeBigInt;
hexString = (hexValue1.Sign == 1 ? "0" : "") + hexValue1.Value;
positiveBigInt = BigInteger.Parse(hexString, NumberStyles.HexNumber);
Console.WriteLine("Converted {0} to {1} and back to {2}.",
positiveNumber, hexValue1.Value, positiveBigInt);
hexString = (hexValue2.Sign == 1 ? "0" : "") + hexValue2.Value;
negativeBigInt = BigInteger.Parse(hexString, NumberStyles.HexNumber);
Console.WriteLine("Converted {0} to {1} and back to {2}.",
negativeNumber, hexValue2.Value, negativeBigInt);
}
}
// The example displays the following output:
// Converted 4039543321 to F0C68A19 and back to 4039543321.
// Converted -255423975 to f0c68a19 and back to -255423975.
Imports System.Globalization
Imports System.Numerics
Public Structure HexValue
Public Sign As Integer
Public Value As String
End Structure
Module Example2
Public Sub Main()
Dim positiveNumber As UInteger = 4039543321
Dim negativeNumber As Integer = -255423975
' Convert the numbers to hex strings.
Dim hexValue1, hexValue2 As HexValue
hexValue1.Value = positiveNumber.ToString("X")
hexValue1.Sign = Math.Sign(positiveNumber)
hexValue2.Value = Convert.ToString(negativeNumber, 16)
hexValue2.Sign = Math.Sign(negativeNumber)
' Round-trip the hexadecimal values to BigInteger values.
Dim hexString As String
Dim positiveBigInt, negativeBigInt As BigInteger
hexString = CStr(IIf(hexValue1.Sign = 1, "0", "")) + hexValue1.Value
positiveBigInt = BigInteger.Parse(hexString, NumberStyles.HexNumber)
Console.WriteLine("Converted {0} to {1} and back to {2}.",
positiveNumber, hexValue1.Value, positiveBigInt)
hexString = CStr(IIf(hexValue2.Sign = 1, "0", "")) + hexValue2.Value
negativeBigInt = BigInteger.Parse(hexString, NumberStyles.HexNumber)
Console.WriteLine("Converted {0} to {1} and back to {2}.",
negativeNumber, hexValue2.Value, negativeBigInt)
End Sub
End Module
' The example displays the following output:
' Converted 4039543321 to F0C68A19 and back to 4039543321.
' Converted -255423975 to f0c68a19 and back to -255423975.