BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

.NET Framework
.NET 4.0+

The BigInteger Structure

Under some circumstances the standard integer data types provided by the .NET framework provide a range of values that is restrictive. The BigInteger structure, introduced in version 4.0 of the framework, removes the size limits.

What is a BigInteger?

The .NET framework version 4.0 introduced a new structure named BigInteger. This structure allows integer values of any size to be represented, unlike the previous integer types that had a fixed range of allowable values. BigIntegers allows you to store and process very large values without the risk of overflow exceptions and without considering the use of checked or unchecked arithmetic in most situations. These improvements do come with some limitations however, as it is not always as easy to work with BigIntegers as it is with the earlier types.

In this article we will see some examples of the use of BigInteger values and the operators, methods and properties of the new structure. To follow the examples, create a new console application. The BigInteger type is found in the System.Numerics.dll assembly, so add a reference to the assembly to your project. Finally, the structure is found in the System.Numerics namespace, so add the following using directive to your code file:

using System.Numerics;

Creating a BigInteger

Instantiating a BigInteger is easy when you wish to initialise it with a value that is within the range of one of the previously available numeric data types. For example, we can create a new BigInteger and apply an integer value to it using the assignment operator as follows:

BigInteger big = 1000000;

The above statement works because the integer types allow implicit casting to BigInteger. We can also instantiate a new BigInteger using the default constructor for the type. In this case the new value will be zero:

BigInteger big = new BigInteger(); // 0

Many other BigInteger constructors exist. Most include a single parameter that is used to initialise the new value. You can pass a 32-bit or 64-bit integer or unsigned integer or a double to the argument. For example, the next line of code initialises a BigInteger with the maximum value that can be assigned to an unsigned 64-bit integer.

BigInteger big = new BigInteger(ulong.MaxValue); // 18446744073709551615

The three methods describe above can only be used to create BigIntegers with values the lie within the range of one of the types available in earlier versions of the .NET framework. This limitation exists because you cannot define a BigInteger literal in C#. If you wish to initialise a variable with a larger value, you can use the final overloaded version of the constructor. This has a single parameter that accepts an array of bytes. The array represents a standard value using little endian byte order, meaning the least significant byte is the first element in the sequence.

BigInteger big = new BigInteger(
    new byte[] { 0, 0, 16, 99, 45, 94, 199, 107, 5 }); // 100000000000000000000

The last method of initialising a BigInteger is to parse a value from a string. This is particularly useful when the value is to be entered by the user. As with other numeric types, the BigInteger structure supports the use of Parse and TryParse to attempt to convert a string to a value. These methods can be used with specified number styles if required. The following simple example uses Parse with default options.

BigInteger big = BigInteger.Parse("100000000000000000000");

BigInteger Operators

Arithmetic Operators

The BigInteger structure supports the common arithmetic operators. These include addition (+), subtraction (-), multiplication (*), division (/) and modulus (%). Each of these can also be used as a compound assignment operator. In addition, the increment (++) and decrement (--) operators can be used. The example code below shows the results of some of these operators. Note that the arithmetic operators with two operands can be used with two BigIntegers or with a single BigInteger and another type.

BigInteger big = BigInteger.Parse("100000000000000000000");
big += 10;  // 100000000000000000010
big -= 1;   // 100000000000000000009
big *= 100; // 10000000000000000000900
big -= 1;   // 10000000000000000000899
big++;      // 10000000000000000000900
big--;      // 10000000000000000000899
big += BigInteger.Parse("100000000000000000000");   // 10100000000000000000899
BigInteger modulus = big % 1000;                    // 899
big = -big; // -899

Logical Bitwise Operators

The logical bitwise operators, AND (&), OR (|) and exclusive OR (^) all work as expected with BigIntegers. You can also obtain the one's complement of a large value (~).

BigInteger big = BigInteger.Parse("100000000000000000000");
big &= BigInteger.Parse("12345678901234567890");    // 3117625691341848576
big |= BigInteger.Parse("55555555555555555555");    // 58509916912771545315
big ^= BigInteger.Parse("55555555555555555555");    // 2954361357215989760
big = ~big;                                         // -58509916912771545316

Bitwise Shift Operators

The third type of operator to consider is the bitwise shift operator. As you may expect, the BigInteger type supports shifting of values to the left (<<) or right (>>). The added benefit with an unrestricted range of values is that shifting to the left never causes an overflow. Shifting to the right causes the least significant bit to be discarded.

BigInteger big = BigInteger.Parse("100000000000000000000");
big <<= 1;  // 200000000000000000000
big >>= 2;  // 50000000000000000000

Relational Operators

Finally, the BigInteger type supports all of the relational operators, allowing you to test equality (==), inequality (!=) or whether one value is greater than another (<, <=, >=, >). These operators work in much the same way as they would with any other numeric type.

bool result;
BigInteger big1 = BigInteger.Parse("100000000000000000000");
BigInteger big2 = BigInteger.Parse("200000000000000000000");

result = big1 == big2;  // false
result = big1 != big2;  // true
result = big1 > big2;   // false
result = big1 >= big2;  // false
result = big1 < big2;   // true
result = big1 <= big2;  // true
5 November 2010