BigInteger - duuuuuuuuże liczby w C#

Nowością na platformie .NET 4.0 jest przestrzeń nazw System.Numeric, która zawiera strukturę BigInteger. Struktury tej, jak sama nazwa wskazuje, używamy gdy chcemy operować na bardzo dużych liczbach całkowitych. BigInteger nie ma teoretycznie ograniczeń w postaci dolnego i górnego limitu w przeciwieństwie do podstawowych typów danych.

Inicjalizacja obiektu typu BigInteger

BigInteger big = new BigInteger();
//jeżeli zmiennej typu BigInteger nie nadamy wartości początkowej w konstruktorze klasy to
//domyślną wartością zmiennej będzie BigInteger.Zero

//nadawanie wartości początkowej zmiennej typu BigInteger w konstruktorze obiektu 
BigInteger bigIntFromDouble = new BigInteger(-123456789.0123456789);
Console.WriteLine(bigIntFromDouble);
//otrzymamy -123456789

BigInteger bigIntFromInt = new BigInteger(9876543210);
Console.WriteLine(bigIntFromInt64);
//otrzymamy 9876543210

//przepisywanie do zmiennej typu BigInteger wartości istniejącej już zmiennej
long longValue = long.MaxValue;
BigInteger assignedFromLong = longValue;
Console.WriteLine(assignedFromLong);
//otrzymamy 9223372036854775807

//liczby zmiennoprzecinkowe też można rzutować na typ Biginteger
BigInteger assignedFromDouble = (BigInteger)12345.6789;
Console.WriteLine(assignedFromDouble);
//otrzymamy 12345

BigInteger assignedFromDecimal = (BigInteger)123.45m;
Console.WriteLine(assignedFromDecimal);
//otrzymamy 123

Dzięki statycznym metodom Parse i TryParse klasy BigInteger do zmiennej typu BigInteger można przepisywać wartości liczbowe z literału tekstowego:

string positiveString = "9999999999999999999999999999999999999999999999999999999999999";
string negativeString = "-1000000000000000000000000000000000000000000000000000000000000000000";
BigInteger posBigInt = 0;
BigInteger negBigInt = 0;

try
{
  posBigInt = BigInteger.Parse(positiveString);
  Console.WriteLine(posBigInt);
  //otrzymamy 9999999999999999999999999999999999999999999999999999999999999
}
catch (FormatException)
{
  Console.WriteLine("Nie można przekonwertować literału '{0}' na wartość typ BigInteger.", positiveString);
}

if (BigInteger.TryParse(negativeString, out negBigInt))
  Console.WriteLine(negBigInt);
  //otrzymamy -1000000000000000000000000000000000000000000000000000000000000000000
else
  Console.WriteLine("Nie można przekonwertować literału '{0}' na wartość typ BigInteger.", negativeString);

Uwaga. Po przepisaniu wartości do zmiennej typu BigInteger nie można tej wartości modyfikować ponieważ dane są niemutowalne. Oznacza to, że gdy zmieniamy dane zapisane w zmiennej BigInteger to de facto tworzymy nowy obiekt tej klasy ze zmienioną odpowiednio wartością.

Operowanie na zmiennych typu BigInteger

Klasa BigInteger zawiera wiele statycznych metod pozwalających na wykonywanie na zmiennych tego typu podstawowych operacji matematycznych np:

string strBig = "-9999999999999999999999999999";
BigInteger bigInt = BigInteger.Parse(strBig);
Console.WriteLine(bigInt); //otrzymamy -9999999999999999999999999999

//pobieranie wartości bezwzględnej ze zmiennej typu BigInteger
BigInteger big1 = BigInteger.Abs(bigInt);
Console.WriteLine(big1); //otrzymamy 9999999999999999999999999999

//dodawanie zmiennych typu BigInteger
//użycie takiego zapisu:
//BigInteger big2 = Int64.MaxValue + Int32.MaxValue;
//spowoduje błąd "The operation overflows at compile time in checked mode"
//zamiast powyższego można tak:
BigInteger big2 = BigInteger.Add(Int64.MaxValue, Int32.MaxValue);
Console.WriteLine(big2); //otrzymamy 9223372039002259454
//lub tak
BigInteger big2 = big1 + big1;

//dzielenie zmiennych typu BigInteger
BigInteger dzielnik = BigInteger.Pow(Int64.MaxValue, 2); //85070591730234615847396907784232501249
BigInteger dzielna = BigInteger.Multiply((BigInteger)Single.MaxValue, 2); //680564693277057719623408366969033850880

BigInteger iloraz = BigInteger.Divide(dzielna, dzielnik); //otrzymamy 7

BigInteger reszta = 0;
iloraz = BigInteger.DivRem(dzielna, dzielnik, out reszta); //reszta = 85070551165415408691630012479406342137

//mnożenie zmiennych typu BigInteger
//użycie takiego zapisu:
//BigInteger big3 = Int64.MaxValue * Int32.MaxValue;
//spowoduje błąd "The operation overflows at compile time in checked mode"
//zamiast powyższego można tak:
BigInteger big3 = BigInteger.Multiply(Int64.MaxValue, Int32.MaxValue);
Console.WriteLine(big3); //otrzymamy 19807040619342712359383728129
//lub tak
BigInteger big3 = big1 * big2;

//wartość przeciwna
BigInteger big4 = new BigInteger(1234567890);

Console.WriteLine(BigInteger.Negate(big4));    // otrzymamy -1234567890
Console.WriteLine(-big4);                      // otrzymamy -1234567890
Console.WriteLine(big4 * BigInteger.MinusOne); // otrzymamy -1234567890

//potęgowanie liczy typu BigInteger
BigInteger big5 = BigInteger.Pow(1234567890, 100);
//powyższy kod oznacza podniesienie liczby 1234567890 do potęgi 100

Praktyczne wykorzystanie zmiennych typu BigInteger

Maksymalną wartością liczbową całkowitą, jaką możemy w .NET przechować w zmiennej to 18,446,744,073,709,551,615 dla typu ulong czyli UInt64. Wartość ta jest jednak za mała jeżeli chcemy policzyć np. silnię liczby 100. Z pomocą przychodzi nam typ BigInteger.

Obliczanie silni:

public static BigInteger Silnia(BigInteger n)
{
    BigInteger retValue = BigInteger.One;

    for (BigInteger i = BigInteger.One; i <= n; i++)
    {
        retValue = retValue * i;
    }

    return retValue;
}
public static BigInteger Silnia(BigInteger n)
{
    if (n <= BigInteger.One)
        return BigInteger.One;
    else
        return (n * Silnia(n - BigInteger.One));
}
public static BigInteger Silnia(BigInteger n)
{
    return n <= BigInteger.One ? BigInteger.One : n * Silnia(n - 1);
}

Obliczanie ciągu Fibonacciego dla dużej ilości wyrazów też wymaga dużych wartości liczbowych, do czego zmienna typu BigInteger nagaje się najbardziej. Ciąg Fibonnacciego oblicza się w następujący sposób: pierwszy wyraz jest równy 0, drugi jest równy 1, każdy następny jest sumą dwóch poprzednich.

public static BigInteger Fibonacci(BigInteger n)
{
    BigInteger prevValue = new BigInteger(-1);
    BigInteger actResult = new BigInteger(1);

    for (BigInteger i = BigInteger.Zero; i <= n; ++i)
    {
        BigInteger suma = actResult + prevValue;
        prevValue = actResult;
        actResult = suma;
    }

    return actResult;
}
public static BigInteger Fibonacci(BigInteger n)
{

    if (n == BigInteger.Zero || n == BigInteger.One)
        return n;
    else
        return Fibonacci(n - 1) + Fibonacci(n - 2);
}
public static BigInteger Fibonacci(BigInteger n)
{

    return (n == BigInteger.Zero || n == BigInteger.One) ? n : Fibonacci(n - 1) + Fibonacci(n - 2);
}

 

Dodaj nowy komentarz

Filtrowany HTML

  • Adresy internetowe są automatycznie zamieniane w odnośniki, które można kliknąć.
  • Dozwolone znaczniki HTML: <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Znaki końca linii i akapitu dodawane są automatycznie.
  • Tekstowe buźki będą zamieniane na ich graficzne odpowiedniki.

Czysty tekst

  • Znaczniki HTML niedozwolone.
  • Adresy internetowe są automatycznie zamieniane w odnośniki, które można kliknąć.
  • Znaki końca linii i akapitu dodawane są automatycznie.
  • Tekstowe buźki będą zamieniane na ich graficzne odpowiedniki.
CAPTCHA
W celu potwierdzenia, że jesteś człowiekiem, prosimy o wykonanie poniższego zadania
Target Image