Click here to Skip to main content
Click here to Skip to main content

Using the .NET Framework BCL Math APIs via C#

, 13 Apr 2011
Rate this:
Please Sign up or sign in to vote.
An article to help the beginning C# student who may need to code Math in school.

Introduction

C# is used in many college math courses. An expert programmer insisted that C# is as strong as FORTRAN. Regardless, this article is strictly meant for the beginner. This means the advanced or intermediate developer should overlook this article. The content will begin by revealing data types via code and then provide a basic program using some of the System.Math APIs. Afterwards, we will try to expand on them and write code to exemplify the power of these Math APIs. The BCL System.Math class provides basic mathematical functions. This class is static and provides methods such as absolute value, floor and ceiling, rounding and truncation, trigonometric functions, exponential operations, logarithmic operations, min and max, amongst others. Let's look at some basic code that makes use of these members. Before we do this, let's review the basic integer data types:

using System;
public class App 
{
    public static void Main()
    {
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(byte).ToString(), sizeof(byte), byte.MinValue, byte.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(char).ToString(), sizeof(char), 
            (int)char.MinValue, (int)char.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(short).ToString(), sizeof(short), 
            short.MinValue, short.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(int).ToString(), sizeof(int), int.MinValue, int.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(long).ToString(), sizeof(long), long.MinValue, long.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(sbyte).ToString(), sizeof(sbyte), 
            sbyte.MinValue, sbyte.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(ushort).ToString(), sizeof(ushort), 
            ushort.MinValue, ushort.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(uint).ToString(), sizeof(uint), uint.MinValue, uint.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
            typeof(ulong).ToString(), sizeof(ulong), 
            ulong.MinValue, ulong.MaxValue);
    }
}

Notice the "typeof" keyword to signify the data type and the numerical range that it covers. Here is the output:

System.Byte:  bytes: 1, range: [0,255]
System.Char:  bytes: 2, range: [0,65535]
System.Int16: bytes: 2, range: [-32768,32767]
System.Int32: bytes: 4, range: [-2147483648,2147483647]
System.Int64: bytes: 8, range: [-9223372036854775808,9223372036854775807]
System.SByte: bytes: 1, range: [-128,127]
System.UInt16: bytes: 2, range: [0,65535]
System.UInt32: bytes: 4, range: [0,4294967295]
System.UInt64: bytes: 8, range: [0,18446744073709551615]

Looking at the above, we see that we do not yet see the decimal, float, or double type:

using System;
public class Program
{
    public static void Main()
    {
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
           typeof(float).ToString(), sizeof(float), float.MinValue, float.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
           typeof(double).ToString(), sizeof(double), double.MinValue, double.MaxValue);
        Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
           typeof(decimal).ToString(), sizeof(decimal), decimal.MinValue, decimal.MaxValue);
    }
}

Notice the use of the sizeof keyword. Now we see these types with their names recognized by the CLR to output their minimum and maximum value:

System.Single: bytes: 4, range: [-3.402823E+38,3.402823E+38]
System.Double: bytes: 8, 
   range: [-1.79769313486232E+308,1.79769313486232E+308]
System.Decimal: bytes: 16, 
   range: [79228162514264337593543950335,79228162514264337593543950335]

Now we can look at an example using some of the System.Math APIs:

using System;   
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Abs({0}) = {1}", -45, Math.Abs(-45));
        Console.WriteLine("Ceiling({0}) = {1}", 45.3, Math.Ceiling(45.3));
        Console.WriteLine("Pow({0},{1}em;) = {2}", 10.5, 3, Math.Pow(10.5, 3));
        Console.WriteLine("Round({0},{1}) = {2}",
            10.55358, 2, Math.Round(10.55358, 2));
        Console.WriteLine("Sin({0}) = {1}", 323.333, Math.Sin(323.333));
        Console.WriteLine("Cos({0}) = {1}", 323.333, Math.Cos(323.333));
        Console.WriteLine("Tan({0}) = {1}", 323.333, Math.Tan(323.333));
        Console.WriteLine("Sinh({0}) = {1}", 323.333, Math.Sinh(323.333));
        Console.WriteLine("Cosh({0}) = {1}", 323.333, Math.Cosh(323.333));
        Console.WriteLine("Tanh({0}) = {1}", 323.333, Math.Tanh(323.333));
    }
}

Here is the output:

Abs(-45) = 45
Ceiling(45.3) = 56
Pow(10.5,3em;) = 1157.625
Round(10.55358,2) = 10.55
Sin(323.333) = 0.248414709883854
Cos(323.333) = -0.968653772982546
Tan(323.333) = -0.256453561440193
Sinh(323.333) = 1.3204067066941E+140
Cosh(323.333) = 1.3204067066941E+140
Tanh(323.333) = 1

Angular Units of Measurement

The numbers we plugged into to the trig functions appeared to provide unusual outputs. In elementary plane geometry, an angle is formally defined by two rays that intersect at the same endpoint. The point where the two rays intersect is called the vertex of the angle, and the two rays themselves are called the sides of the angle. An arbitrary angle, say θ, is then measured by the first drawing a circular arc of length, say s, which is centered at the vertex of the angle such that it intersects both of its sides. Then the length of the arc s is divided by the radius r of the corresponding circle so that the angle θ = s/r. Since they are defined as the ratio of lengths, angles are considered dimensionless. Nevertheless, there are several units used to measure angles, the most common of which are the radian and the degree. The angle subtended at the center of a circle by an arc that is equal in length to the radius of the circle is defined to be one radian. The degree, denoted by a small superscript circle (◦) is 1/360 of a full circle. Therefore, one full circle is 360◦ or 2π radians, and one radian is 180◦/π degrees, or about 57.2958◦. The radian is the preferred unit of angular measurement in the metric system and is abbreviated rad.

Here is the code to perform the translation between degrees and radians:

using System;
public class Program {
    public static double DegreesToRadians(double degrees)
    {
        return (Math.PI / 180.0) * degrees;
    }

    public static double RadiansToDegrees(double radians)
    {
        return (180.0 / Math.PI) * radians;
    }

    public static double GradsToRadians(double grads)
    {
        return (grads / 200.0) * Math.PI;
    }

    public static double RadiansToGrads(double radians)
    {
        return (radians / Math.PI) * 200.0;
    }

    public static double DegreesToGrads(double degrees)
    {
        return (degrees / 9.0) * 10.0;
    }

    public static double GradsToDegrees(double grads)
    {
        return (grads / 10.0) * 9.0;
    }

   
    public static double Sec(double x)
    {
        return (1.0 / Math.Cos(x));
    }

    public static double Csc(double x)
    {
        return (1.0 / Math.Sin(x));
    }

    public static double Cot(double x)
    {
        return (Math.Cos(x) / Math.Sin(x));
    }

    public static void Main()
    {
        Console.WriteLine("\n--- RUNNING TRIG FUNCTIONS EXAMPLE ---\n");
        for (double angleDEG = 0.0; angleDEG <= 360.0; angleDEG += 45.0)
        {
            double angleRAD = DegreesToRadians(angleDEG);
            Console.WriteLine("Angle = {0}\xb0", angleDEG);
            Console.WriteLine("cos({0}\xb0) = {1}", angleDEG, Math.Cos(angleRAD));
            Console.WriteLine("sin({0}\xb0) = {1}", angleDEG, Math.Sin(angleRAD));
            Console.WriteLine("tan({0}\xb0) = {1}", angleDEG, Math.Tan(angleRAD));
            Console.WriteLine("sec({0}o) = {1}", angleDEG, Sec(angleRAD));
            Console.WriteLine("csc({0}o) = {1}", angleDEG, Csc(angleRAD));
            Console.WriteLine("cot({0}o) = {1}", angleDEG, Cot(angleRAD));
            Console.WriteLine("--------------------------------------------\n");
        }
        Console.WriteLine("--------------------------------------------\n");
    }
}

Consider the 45 degree angle. The value of the sin and the cos of 45 are both .707. This number is the inverse of the square root of two. This means that the triangle formed by the unit circle has two sides equal to one, with the other equal to the square root of two. Here is the output:

--- RUNNING TRIG FUNCTIONS EXAMPLE ---

Angle = 0°
cos(0°) = 1
sin(0°) = 0
tan(0°) = 0
sec(0o) = 1
csc(0o) = Infinity
cot(0o) = Infinity
--------------------------------------------

Angle = 45°
cos(45°) = 0.707106781186548
sin(45°) = 0.707106781186547
tan(45°) = 1
sec(45o) = 1.41421356237309
csc(45o) = 1.4142135623731
cot(45o) = 1
--------------------------------------------

Angle = 90°
cos(90°) = 6.12303176911189E-17
sin(90°) = 1
tan(90°) = 1.63317787283838E+16
sec(90o) = 1.63317787283838E+16
csc(90o) = 1
cot(90o) = 6.12303176911189E-17
--------------------------------------------

Angle = 135°
cos(135°) = -0.707106781186547
sin(135°) = 0.707106781186548
tan(135°) = -1
sec(135o) = -1.4142135623731
csc(135o) = 1.41421356237309
cot(135o) = -1
--------------------------------------------

Angle = 180°
cos(180°) = -1
sin(180°) = 1.22460635382238E-16
tan(180°) = -1.22460635382238E-16
sec(180o) = -1
csc(180o) = 8.16588936419192E+15
cot(180o) = -8.16588936419192E+15
--------------------------------------------

Angle = 225°
cos(225°) = -0.707106781186548
sin(225°) = -0.707106781186547
tan(225°) = 1
sec(225o) = -1.41421356237309
csc(225o) = -1.4142135623731
cot(225o) = 1
--------------------------------------------

Angle = 270°
cos(270°) = -1.83690953073357E-16
sin(270°) = -1
tan(270°) = 5.44392624279462E+15
sec(270o) = -5.44392624279462E+15
csc(270o) = -1
cot(270o) = 1.83690953073357E-16
--------------------------------------------

Angle = 315°
cos(315°) = 0.707106781186547
sin(315°) = -0.707106781186548
tan(315°) = -1
sec(315o) = 1.4142135623731
csc(315o) = -1.41421356237309
cot(315o) = -1
--------------------------------------------

Angle = 360°
cos(360°) = 1
sin(360°) = -2.44921270764475E-16
tan(360°) = -2.44921270764475E-16
sec(360o) = 1
csc(360o) = -4.08294468209596E+15
cot(360o) = -4.08294468209596E+15
--------------------------------------------

OK. This is not so bad, is it? Now let's briefly examine the Power, Log, Exponent, Min, and Max operations. The .NET Framework Math Class Library provides two methods for comparing the relative size of numbers. The Math.Min method returns the smaller of two numbers whereas the Math.Max method returns the larger of two numbers. The general exponential function with a fixed real number base b > 1 and a real number power x is the function expressed by the formula f (x) = bx. The number x is called the exponent and the expression bx is known formally as the exponentiation of b by x or the exponential of x with base b. It is also more commonly expressed as the xth power of b, b to the xth power, or b to the power x. The most commonly used bases are the natural base e and the base 10. If the base equals the Euler number e, then the exponential function is called the natural exponential function and is expressed by f (x) = ex = exp(x).

The inverse of any exponential function is called the logarithmic function with base b and is denoted by logb. Thus logb bx = x. The logarithm of a number to a given positive real number base is the power or exponent to which the base must be raised in order to produce the number. By definition, the logarithm of x to a base b is written as logb(x) or, if the base is implicit, as log(x). Hence, for a number x, a base b, and an exponent y, if x = by then y = logb(x). Here is the sample code, and notice the inverse operations by examining the values. Also note that the numbers PI and E are included, to show how the .NET Framework repeats their repeating decimals:

using System;
public static class Program 
{
    public static void PI_AND_E_Example()
    {
        Console.WriteLine("--- RUNNING Math.PI and Math.E EXAMPLE ---\n");
        Console.WriteLine("PI = {0}", Math.PI);
        Console.WriteLine("E  = {0}", Math.E);
        Console.WriteLine("\n------------------------------------------\n");
    }

    public static void MinMax_Example()
    {
        double x = 5.0, y = 10.0;

        Console.WriteLine("----- RUNNING Math.Min/Max EXAMPLE -----\n");
        Console.WriteLine("The smaller of {0} and {1} is {2}.", x, y, Math.Min(x, y));
        Console.WriteLine("The greater of {0} and {1} is {2}.", x, y, Math.Max(x, y));
        Console.WriteLine("\n----------------------------------------\n");
    }

    public static void PowExpLogLog10_Example()
    {
        double b = 2.75, x = 3.25, newBase = 8;

        Console.WriteLine("--- RUNNING Math.Pow/Exp/Log/" + 
                          "Log10/Log(x,newBase) EXAMPLE ---\n");
        Console.WriteLine("Exp({0}) = {1}", x, Math.Exp(x));
        Console.WriteLine("Log({0}) = {1}\n", Math.Exp(x), Math.Log(Math.Exp(x)));

        Console.WriteLine("Pow({0},{1}) = {2}", b, x, Math.Pow(b, x));
        Console.WriteLine("Log10({0})/Log10({1}) = {2}\n", 
          Math.Pow(b, x), b, Math.Log10(Math.Pow(b, x)) / Math.Log10(b));

        Console.WriteLine("Log{0}({1}) = {2}", newBase, x, Math.Log(x, newBase));
        Console.WriteLine("Pow({0},{1}) = {2}", newBase, 
          Math.Log(x, newBase), Math.Pow(newBase, Math.Log(x, newBase)));
        Console.WriteLine("---------------------------------" + 
                          "----------------------------\n");
    }

    public static void Main(string[] args)
    {
        PI_AND_E_Example();
        Console.ReadLine();

        MinMax_Example();
        Console.ReadLine();

        PowExpLogLog10_Example();
        Console.ReadLine();
    }
}

Here is the output:

--- RUNNING Math.PI and Math.E EXAMPLE ---

PI = 3.14159265358979
E  = 2.71828182845905

------------------------------------------
----- RUNNING Math.Min/Max EXAMPLE -----

The smaller of 5 and 10 is 5.
The greater of 5 and 10 is 10.
--- RUNNING Math.Pow/Exp/Log/Log10/Log(x,newBase) EXAMPLE ---

Exp(3.25) = 25.7903399171931
Log(25.7903399171931) = 3.25

Pow(2.75,3.25) = 26.7812753660606
Log10(26.7812753660606)/Log10(2.75) = 3.25 // notice the symmetry 

Log8(3.25) = 0.566813239380364
Pow(8,0.566813239380364) = 3.25

Inverse Hyperbolic Functions

The hyperbolic functions are related to the hyperbola in much the same way that trigonometric functions are related to the unit circle. For example, the trigonometric functions cos x and sin x are related to a circle of radius r.

using System;
public static class Program
{
    public static double DegreesToRadians(double degrees)
    {
        return (Math.PI / 180.0) * degrees;
    }

    public static double RadiansToDegrees(double radians)
    {
        return (180.0 / Math.PI) * radians;
    }

    public static double GradsToRadians(double grads)
    {
        return (grads / 200.0) * Math.PI;
    }

    public static double RadiansToGrads(double radians)
    {
        return (radians / Math.PI) * 200.0;
    }

    public static double DegreesToGrads(double degrees)
    {
        return (degrees / 9.0) * 10.0;
    }

    public static double GradsToDegrees(double grads)
    {
        return (grads / 10.0) * 9.0;
    }

    public static double ASinh(double x)
    {
        return (Math.Log(x + Math.Sqrt(x * x + 1.0)));
    }

    public static double ACosh(double x)
    {
        return (Math.Log(x + Math.Sqrt((x * x) - 1.0)));
    }

    public static double ATanh(double x)
    {
        return (Math.Log((1.0 + x) / (1.0 - x)) / 2.0);
    }

    public static double ACoth(double x)
    {
        //return (Math.Log((x + 1.0) / (x - 1.0)) / 2.0);
        return (ATanh(1.0 / x));
    }

    public static double ASech(double x)
    {
        return (ACosh(1.0 / x));
    }

    public static double ACsch(double x)
    {
        return (ASinh(1.0 / x));
    }

    public static double Sech(double x)
    {
        return (1.0 / Math.Cosh(x));
    }

    public static double Csch(double x)
    {
        return (1.0 / Math.Sinh(x));
    }

    public static double Coth(double x)
    {
        return (Math.Cosh(x) / Math.Sinh(x));
    }

    public static void Main()
    {
        Console.WriteLine("\n--- RUNNING INVERSE HYPERBOLIC FUNCTIONS EXAMPLE ---\n");
        for (double angleDEG = 0.0; angleDEG <= 360.0; angleDEG += 45.0)
        {
            double angleRAD = DegreesToRadians(angleDEG);
            Console.WriteLine("Angle = {0}\xb0", angleDEG);
            Console.WriteLine("ACosh({0}) = {1}\xb0", 
               Math.Cosh(angleRAD), RadiansToDegrees(ACosh(Math.Cosh(angleRAD))));
            Console.WriteLine("ASinh({0}) = {1}\xb0", 
               Math.Sinh(angleRAD), RadiansToDegrees(ASinh(Math.Sinh(angleRAD))));
            Console.WriteLine("ATanh({0}) = {1}\xb0", 
               Math.Tanh(angleRAD), RadiansToDegrees(ATanh(Math.Tanh(angleRAD))));
            Console.WriteLine("ASech({0}) = {1}o", 
               Sech(angleRAD), RadiansToDegrees(ASech(Sech(angleRAD))));
            Console.WriteLine("ACsch({0}) = {1}o", 
               Csch(angleRAD), RadiansToDegrees(ACsch(Csch(angleRAD))));
            Console.WriteLine("ACoth({0}) = {1}o", 
               Coth(angleRAD), RadiansToDegrees(ACoth(Coth(angleRAD))));
            Console.WriteLine("--------------------------------------------\n");
        }
    }
}

And the output:

--- RUNNING INVERSE HYPERBOLIC FUNCTIONS EXAMPLE ---

Angle = 0°
ACosh(1) = 0°
ASinh(0) = 0°
ATanh(0) = 0°
ASech(1) = 0o
ACsch(Infinity) = 0o
ACoth(Infinity) = 0o
--------------------------------------------

Angle = 45°
ACosh(1.32460908925201) = 45°
ASinh(0.86867096148601) = 45°
ATanh(0.655794202632672) = 45°
ASech(0.754939708714131) = 45o
ACsch(1.15118387092085) = 45o
ACoth(1.52486861882206) = 45o
--------------------------------------------

Angle = 90°
ACosh(2.50917847865806) = 90°
ASinh(2.30129890230729) = 90°
ATanh(0.917152335667274) = 90°
ASech(0.398536815338387) = 90o
ACsch(0.434537208094696) = 90o
ACoth(1.09033141072737) = 90o
--------------------------------------------

Angle = 135°
ACosh(5.32275214951996) = 135°
ASinh(5.2279719246778) = 135°
ATanh(0.982193380007239) = 135°
ASech(0.187872734237717) = 135o
ACsch(0.191278762473773) = 135o
ACoth(1.01812944411479) = 135o
--------------------------------------------

Angle = 180°
ACosh(11.5919532755215) = 180°
ASinh(11.5487393572577) = 180°
ATanh(0.99627207622075) = 180°
ASech(0.0862667383340544) = 180o
ACsch(0.086589537530047) = 180o
ACoth(1.00374187319732) = 179.999999999999o
--------------------------------------------

Angle = 225°
ACosh(25.3868611923608) = 225°
ASinh(25.3671583193742) = 225°
ATanh(0.999223894878641) = 225°
ASech(0.0393904544726038) = 225o
ACsch(0.0394210493508944) = 225o
ACoth(1.00077670792836) = 225o
--------------------------------------------

Angle = 270°
ACosh(55.6633808904387) = 270°
ASinh(55.6543975994175) = 270°
ATanh(0.999838613988633) = 269.999999999992°
ASech(0.017965132264752) = 270o
ACsch(0.0179680320537773) = 270o
ACoth(1.00016141206102) = 269.999999999992o
--------------------------------------------

Angle = 315°
ACosh(122.077579339582) = 315°
ASinh(122.073483514693) = 315°
ATanh(0.999966448999796) = 315.00000000001°
ASech(0.00819151235967997) = 315o
ACsch(0.00819178720233407) = 315o
ACoth(1.00003355212591) = 315.00000000001o
--------------------------------------------

Angle = 360°
ACosh(267.746761483748) = 360°
ASinh(267.744894041016) = 360°
ATanh(0.999993025339611) = 360.000000000173°
ASech(0.00373487243863713) = 360o
ACsch(0.00373489848828567) = 360o
ACoth(1.00000697470904) = 359.999999999717o

The above source code only touches the surface of the power of both C# and the BCL's System.Math class APIs. Again, this article has been written for the beginner.

References

  • The MSDN Library
  • Professional .NET Framework 2.0, written by Joe Duffy

License

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

About the Author

logicchild
Other Pref. Trust
United States United States
I started electronics training at age 33. I began studying microprocessor technology in an RF communications oriented program. I am 43 years old now. I have studied C code, opcode (mainly x86 and AT+T) for around 3 years in order to learn how to recognize viral code and the use of procedural languages. I am currently learning C# and the other virtual runtime system languages. I guess I started with the egg rather than the chicken. My past work would indicate that my primary strength is in applied mathematics.

Comments and Discussions

 
Generalmy 5 PinmemberSouthmountain31-Oct-13 5:44 
Generalstatement Pinmemberhajovonta19-Apr-11 1:42 
General¿Error? Pinmemberlinebenchmark13-Apr-11 16:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140709.1 | Last Updated 13 Apr 2011
Article Copyright 2011 by logicchild
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid