Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

A BigNumber Class Done in C#

4.80/5 (26 votes)
3 Sep 2009CPOL2 min read 67.4K   1.1K  
A simple C# library for doing math calculations in any desired precision

Introduction

I wanted to write a simple library for C# that allows to do math calculations at any desired precision level.

Background

During the last few months, I have been playing around with math libraries, and started to implement my own precision math library. I stumbled upon the MAPM library (http://www.tc.umn.edu/~ringx004/mapm-main.html) and decided to create something similar for .NET. This library is the result of my work. Basically. it is a rewrite of the MAPM library for .NET.

My goal is to use this library inside a Mandelbrot fractal renderer I have posted here on CodeProject. Theoretically, this should provide endless zooming into the fractal (at the expense of speed). We will soon see what happens ;-)

Using the Code

The header of the Big Num class looks like this:

C#
public partial class BigNumber
{
        sbyte signum=0;
        int exponent=0;
        byte[] mantissa= {0};
        int dataLength=1; 
        
        ...
}

A big number is represented in the form of S * A * 10 ^ B where:

  • S ... is the signum
  • A ... is the mantissa
  • B ... is the exponent

The mantissa is represented as an array of packed bytes.
Each nibble of a byte represents 2 digits of the number.
The mantissa can have an arbitrary length. It is limited to 1 < |a| < 10

Open the project, compile, and run. The included test program will call the function DoTest() of the library.

Have a look at the DoTest() function to see how to work with this library. You will find examples of how to:

  • assign values to BigNumbers
  • do basic math operations using the overloaded operators +, -, *, and /
  • use math functions like rounding sqrt, pow, log10, log2, and more
  • calculate 1000! using this library
  • calculate the number PI to a desired amount of digits
C#
public static void DoTest()
{
    BigNumber A = 0, B = 0, C = 0;
    BigNumber PI= new BigNumber();

    // assignment by string
    A = "12345";
    Console.WriteLine("assigned value was: " + A.ToFullString() + 
                      "(" + A.ToString() + ")");

    // assignment by double
    A = 123.45;
    Console.WriteLine("assigned value was: " + A.ToFullString() + 
                      "(" + A.ToString() + ")");

    // assignment by string in exponential form x = a*10^y. 10E3 = 10*10^^3 = 10000
    A = "10E3";     // 10E3 = 10*10^3 = 10000
    B = "1E4";      // 1E4  =  1*10^4 = 10000
    C = 10000;
    Console.WriteLine("assigned value was: " + A.ToFullString() + 
                      "(" + A.ToString()+")");
    Console.WriteLine("10000 = " + A.ToFullString() + " = " + 
                      B.ToFullString() + " = " + C.ToFullString());
    
    A = 1; B = 2; C = 0;
    C = A + B;
    Console.WriteLine("the result of " + A.ToFullString() + "+" + 
                      B.ToFullString() + "=" + C.ToFullString());
    // addition of BigNumber + double
    C = A + 3.2;
    // addition of double + BigNumber
    C = 3.1 + B;             
    A = "5.141592"; B = "2.91827";
    C = A - B;
    Console.WriteLine("the result of " + A.ToFullString() + 
                      "-" + B.ToFullString() + "=" + C.ToFullString());

    C = A * B;
    Console.WriteLine("the result of " + A.ToFullString() + 
                      "*" + B.ToFullString() + "=" + C.ToFullString());
    A = 5.0; B = 3.0;
    C = A * B;
    Console.WriteLine("the result of " + A.ToFullString() + 
                      "*" + B.ToFullString() + "=" + C.ToFullString());

    A = 4; B = 0.5;
    C = A.Pow(B);
    Console.WriteLine("the result of " + A.ToFullString() + 
                      " pow " + B.ToFullString() + "=" + C.ToFullString());

    A = 0.5; B = "5E-1";  
    C = A.Pow(B,16);
    Console.WriteLine("the result of " + A.ToFullString() + 
                      " pow " + B.ToFullString() + "=" + C.ToFullString());

    A = "1e3"; // "10E2"; //   "1E3 = 1000";
    C = A.Log10();
    Console.WriteLine("the result of " + A.ToFullString() + 
                      " Log10 =" + C.ToFullString());
   
    A = "10E3"; B = "1E4"; C=10000 ;

    A = BigNumber.BN_E;
    C = A.Log();
    Console.WriteLine("the result of " + A.ToString() + 
                      " Log =" + C.ToFullString());

    A = 3.0;
    C = A.Rez();
    Console.WriteLine("the result of " + A.ToString() + 
                      " Rez =" + C.ToFullString());

    int NumPlaces = 4;
    A = 1.53456;
    C = A.Round(NumPlaces);
    Console.WriteLine("the result of " + A.ToString() + 
                      " Round(" + NumPlaces + ") =" + 
                      C.ToFullString());

    NumPlaces = 2;
    C = A.Round(NumPlaces);
    Console.WriteLine("the result of " + A.ToString() + 
                      " Round(" + NumPlaces + ") =" + 
                      C.ToFullString());

    NumPlaces = 0;
    C = A.Round(NumPlaces);
    Console.WriteLine("the result of " + A.ToString() + 
                      " Round(" + NumPlaces + ") =" + 
                      C.ToFullString());

    NumPlaces = 16;
    A = 2.0;
    C = A.Sqrt(NumPlaces);
    Console.WriteLine("the result of " + A.ToString() + 
                      " Sqrt(" + NumPlaces + ") =" + 
                      C.ToFullString());

    A = 1.0; B = 0;
    try
    {
        C = A / B;
    }
    catch (BigNumberException ex)
    {
        Console.WriteLine("Exception in operation: " + ex.Message);
    }

    A = 1.0;
    for (int i = 1; i <= 1000; i++)
    {
        A = A * i;
    }
             
    Console.WriteLine("the result of 1000!=" + A.ToFullString());
    A = A.Round(numDefaultPlaces);
    Console.WriteLine("the result of 1000!=" + A.ToString());

    DateTime before = DateTime.Now;

    NumPlaces = 5000;
    CalculatePiAGM(PI, NumPlaces);

    TimeSpan ts = DateTime.Now - before;
    Console.WriteLine("time for "+NumPlaces+" digits of PI: " + 
                      ts.TotalMilliseconds + "[ms]");
    Console.WriteLine(PI.ToFullString());

    Console.WriteLine("Press 'x' key to quit test");
    while (true)
    {
        ConsoleKeyInfo i = Console.ReadKey();
        if (i.KeyChar == 'x') break;
    }
}

History

  • 31.08.2009
    • Initial release
  • 03.09.2009 
    • Implemented setting values from binary and hex strings
    • Fixed a bug in the add function

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)