In addition to string, another extremely important entity that lays at the foundation of any software application is the numbers. Numbers play a very crucial role, particularly in the business logic layer of any software application. Logic building requires strong knowledge of numbers and their usage. For instance, if you want to fetch the records of all the employs from a database where salary is greater than Rs. 20,000, you must know how to use numbers; how to do number conversions and what mathematical formulas to use in order to achieve the desired functionality such as squaring the terms, getting square roots etc. Fortunately, enough .NET Framework provides multiple numeric types and the classes that can be used for manipulating those numeric types. In this article, we will discuss some of the most important types associated with numbers. Static Math Class Using BigInteger struct to store large integer values Using Complex struct Random Number Generation Static Math Class The first and foremost class that you should have complete understanding of, is the static Math class that provides several built-in mathematical functions that can be used to manipulate numbers. Several mathematical constants, such as E(e), and PI are also defined in the mathematics class. Following are some of the most widely used methods of the static mathematics class. Round - This method is simply used to round off a number. For instance, if you pass a number 10.4 as argument to this method, it will round off it and return 10. Truncate - This method is used to truncate the decimal part of a number and returns the integer part. For instance if you pass 10.4 to this method, it will truncate .4 and will return an integer 10. Floor - The floor method also rounds number off but it rounds off the number down to the nearest integer, for instance if you pass it a number 10.4 it will return an integer 10; if you pass it the number 10.9, it will still return number 10 because it has to round number off to the nearest lower integer which is 10 in both cases. Ceiling - This function does exactly the reverse of the Floor method; it takes a number and round it up to the nearest integer. For instance, if you pass 10.4 to this method it will round it to 11. Floor and Ceiling functions are self-explanatory; floor means the floor used in sense lower limit and the ceiling is the upper limit of a room. This is a good way to remember these functions. Max/Min - These methods take two values and return the maximum or minimum of those two values. By default, these methods take two numeric values, however if you want to find the maximum or minimum values of a sequence of number or an array, you can use the extensions of these two methods which are available in System.Linq.Enumerable. Pow - This method takes two parameters, the first parameter is the number which you want to raise to a power and the second number is the power. For instance, if you pass two numbers such as Math.Pow(4, 2). It means that we want to raise 4 to the power 2, which will return 16. Log and Log10 - These two methods are used to calculate logarithm of number. Simple Log function is used to calculate natural log to the base (e) of specified number whereas Log10 returns the log of a number to base 10. Trigonometric Functions - Following are the trigonometric functions available in static Math class. Sin Cos Tan Sinh Cosh Tanh Asin Acos Atan Now, we will put whatever we have studied till now in a working Example. We have implemented all the aforementioned methods in Example1. Have a look at Example1. Example1 Code: using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Text; using System.Globalization; namespace CSharpTutorial { class Program { public static void Main() { Console.WriteLine("Important Methods in The Match Class\n"); Console.WriteLine("************************************"); Console.Write("Rounding off a number 10.4: "); Console.Write(Math.Round(10.4)); Console.Write("\nTruncating number 10.4: "); Console.Write(Math.Truncate(10.4)); Console.Write("\nFloor on number 10.4: "); Console.Write(Math.Floor(10.4)); Console.Write("\nCeiling on number 10.4: "); Console.Write(Math.Ceiling(10.4)); Console.Write("\nChoosing maximum from 10 and 12: "); Console.Write(Math.Max(10, 12)); Console.Write("\nChoosing minumum from 10 and 12: "); Console.Write(Math.Min(10, 12)); Console.Write("\nTaking square root of any number such as 16: "); Console.Write(Math.Sqrt(16)); Console.Write("\nRaising number 4 to power 2: "); Console.Write(Math.Pow(4,2)); Console.Write("\nTaking log of a number 10: "); Console.Write(Math.Log(100)); Console.Write("\nTaking base 10 log of a number 100: "); Console.Write(Math.Log10(100)); Console.Write("\nTaking sin of 90: "); Console.Write(Math.Sin(120)); Console.ReadLine(); } } } In Example1, we have simply implemented all the functions of the static Math class that we mentioned above and have then displayed the returned value on the output screen. This example should give you a thorough understanding of how these functions actually are implemented in real life applications and what are their results. I would suggest you to change the values in this example to see if the functions give you the desired result or not. Here is the output of Example1. Output1 Using BigInteger struct to store large integer values A simple integer cannot store very large values, for example if you want to store a number like 10000000000000000000000000000000000000000000000 i.e. a number with 1 followed by 100 zeros or the number of order 10 raise to power 100. If you try to store such number, the compiler might through an exception or even if it doesn’t throw an exception, it will result in loss of precision and the integer might not contain the complete value. For this reason, from .NET Framework 4.0, a new numeric struct has been introduced in the .NET Framework which allows us to store large integer value. BigInteger is the struct that allows us to store large integer values in a struct. By default, C# haven’t got any literal to represent a large value to store in the BigInteger struct however you can store an integer value to BigInteger without having implicitly parse it. For instance you can do BigInteger num = 25 // Here 25 is an integer literal being stored in the BigInteger struct. In order to declare a number of order 10 raise to the power 10, you have to methods. You can either use the Pow static method of the Math class, or you can achieve this functionality via parsing like this Parse("1".PadRight(100, '0')). Another very interesting to note here is that you can explicitly convert BigInteger to double and int values and vice versa but that may result in the loss precision. Now as usual, we will implement BigInteger struct in our example to further elaborate the concept. Have a look at Example2. Example2 Code: using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Text; using System.Numerics; namespace CSharpTutorial { class Program { public static void Main() { BigInteger num = BigInteger.Parse("1".PadRight(100, '0')); Console.WriteLine(num); num = BigInteger.Pow(10, 100); Console.WriteLine(num); Console.WriteLine("Loss of precision"); double dnum = (double)num; Console.WriteLine(dnum); Console.ReadLine(); } } } First of all, add the reference to System.Numerics dll to your project and then import System.Numeric namespace to your code. This will allow you to use BigInteger struct in your code. In the next lines of code we have stored a very large value 10 ^ 100 in the BigInteger ‘num’. BigInteger struct also contains static method that can be used to generate very large values. We have then, parsed a string with 1 and followed 100 zeros into BigInteger type by calling the Parse method on BigInteger. Next we have converted ‘num’ to double value dnum. This should result in the loss of precision as we shall see in the output. The output of the code in Example2 is as follows. Output2 BigInteger struct overloads almost of the arithmetic operators that operate on numeric types including the comparison operator and the % operator for remainder calculation. Using Complex struct Another very useful struct that was introduced with .NET Framework 4.0 was the complex struct which is used for storing complex numbers. Complex struct also belong to the same System.Numerics namespace like BigInteger. Complex struct can store a complex number which has two parts i.e a real part and an imaginary part. In order to declare a complex struct you simply have to write this line of code Code: Complex num1 = new Complex(5, 1.5); Here 5 is the real part and 1.5 will be the imaginary part. You can also implicitly convert numeric types to complex types, for example you store an integer in Complex struct like Complex num3 = 25; Our next example throws light on this concept. Example3, implements the aforementioned concepts. Have a look at it. Example3 Code: using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Text; using System.Numerics; namespace CSharpTutorial { class Program { public static void Main() { Console.WriteLine("Working with complex numbers.\n"); Complex num1 = new Complex(5, 1.5); Console.WriteLine("Accessing Real part ..."); Console.WriteLine(num1.Real); Console.WriteLine("\nAccessing imaginary part ..."); Console.WriteLine(num1.Imaginary); Console.WriteLine("\nAccessing magnitude ..."); Console.WriteLine(num1.Magnitude); Console.WriteLine("\nAccessing phase ..."); Console.WriteLine(num1.Phase); Console.WriteLine("\nPerforming arithmetic on complex number\n"); Complex num2 = new Complex(4, 5); Console.WriteLine(num1 + num2); Console.WriteLine(num1 * num2); Console.ReadLine(); } } } In Example3, we have declared a Complex struct and named it num1; we have passed it two parameters: 5 and 1.5 which are its real and imaginary parts respectively. We have then simply printed these values on screen along with default values of magnitude and phase. Next we have declared another Complex struct and we have named that struct as num2. Complex struct, like BigInteger overloads all the basic arithmetic and comparison operator. Therefore in the next lines of code in Example5, we have declared another Complex struct and have named it num2. It has real and imaginary parts of 4 and 5 respectively. Next we simply added and multiplied num1 and num2 and then displayed the result on the output screen. The output of the code in Example3 is as follows. Output3 Random Number Generation In the last section of the article, we will introduce you to the random class that is used to instantiate random numbers. Instantiating random numbers is an extremely simple task. You have to create an object of random class like this Code: Random num1 = new Random(); And then you simply have to call Next function on the object to get a value. For example, if you call num1.Next(), it will generate any random number. However, you can also specify the limit in which the number should be generated. For this purpose, the Next method has two overloads: Next(int maxvalue) - Here you specify maximum limit for the number to be generated randomly, for example if you specify 100 in the parameter, the random number generated will not be greater than 100. Next(int minval, int maxval) - Here in this method the first parameter is the minimum limit and the second parameter is the maximum limit of the number to be generated. Now will put these concepts in the form of a working example, we have implemented these functions in the last example of this article. Have a look at Example4. Example4 Code: using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Text; using System.Numerics; namespace CSharpTutorial { class Program { public static void Main() { Console.WriteLine("Generating Random Numbers ...\n"); Console.WriteLine("\nGenerating purely random numbers ..."); Random num1 = new Random(); Console.WriteLine(num1.Next()); Console.WriteLine("\nGenerating random numbers by specifying upper limit."); Console.WriteLine(num1.Next(50)); Console.WriteLine("\nGenerating random numbers by specifying lower and upper limit."); Console.WriteLine(num1.Next(50,100)); Console.ReadLine(); } } } The code in Example4 is pretty straight forward we declared a Random object and named it ‘num1’, we then simply called Next() method on that and displayed the result. It will generate any random number. Next we again called the Next() method but this time we passed it one parameter which is upper limit by default; we passed it value 50, so the number randomly generated would not be greater than 50. Finally, we again called the Next() method on the num1 object but this time we passed it two parameter, the first one is the lower limit and the second one will be the upper limit and this time it will return some random number between 50 and 100 as we specified. The output of this code is as follows. Output4