An introduction to numerical programming in C#

, 26 Jun 2014 Public Domain
 Rate this:
Please Sign up or sign in to vote.
Some of the first things you need to know when writing numerical software in C#.

Introduction

The first time you write numerical software in a new programming language, you ask the following questions:

• How do I import the standard math library?
• How do I use common math functions?
• What math functions are included and which ones will I need to write or find elsewhere?

For example, in C, you need to add `#include "math.h"` before you call any math functions. Then you can call functions by their traditional names. To find the sine of a number `x`, for example, you simply call `sin(x)`.

In Python, you need to add `import math` to the top of your source file. Math functions typically have the same names as in C, but the functions are methods on a class called `math` rather than global functions. Not as many math functions are available as in C, but you can use SciPy to access an enormous collection of math functions.

What do you have to do in C#? Any gotchas? What's available and what's not?

C# mathematical functions

In C#, mathematical functions are static methods on the `System.Math` class. You don't have to add any references. You probably want to add `using System;` at the top of your files so you can just type `Math` rather than `System.Math` every time you need to call a method.

Functions in `System.Math` follow .NET naming conventions, and so start with capital letters. Otherwise, function names for mathematical functions are often the same as in C. For example, the C functions `exp` and `cos` are `Math.Exp` and `Math.Cos` in C#. However, there are a few differences. The following table compares C and C# function names.

C System.Math
`acos` `Acos`
`asin` `Asin`
`atan` `Atan`
`ceil` `Ceiling`
`cos` `Cos`
`cosh` `Cosh`
`exp` `Exp`
`fabs` `Abs`
`floor` `Floor`
`fmod` `IEEERemainder`
`log` `Log`
`log10` `Log10`
`pow` `Pow`
`sin` `Sin`
`sinh` `Sinh`
`sqrt` `Sqrt`
`tan` `Tan`
`tanh` `Tanh`

Notice that there are three exceptions to the pattern that C# function names are simply capitalizations of C names: `Ceiling`, `Abs`, and `IEEERemainder`.

There are a couple functions from the C math library that are methods on `double` rather than on `System.Math`. The `double` class has methods `IsNan` and `IsFinite` corresponding to the methods `isnan` and `isfinite` in math.h. (Visual Studio's version of math.h has a function `_isnan`, but does not have a function corresponding to `isfinite`.)

Numeric limits

Numeric limits in C# have a couple surprises for C and C++ programmers.

In C#, `double.MaxValue` is the largest finite value of a `double`, corresponding to `DBL_MAX` in C. However, the constant `double.MinValue` is not the same as `DBL_MIN` in C. Also, the constant `double.Epsilon` does not correspond to `DBL_EPSILON` in C. This may be the biggest pitfall for programmers coming from C or related languages.

The following code prints the numeric limits from float.h:

```printf("DBL_MAX     = %g\n", DBL_MAX);
printf("DBL_MIN     = %g\n", DBL_MIN);
printf("DBL_EPSILON = %g\n", DBL_EPSILON);```

The output is as follows:

```DBL_MAX     = 1.79769e+308
DBL_MIN     = 2.22507e-308
DBL_EPSILON = 2.22045e-016```

(The constants `DBL_MAX`, `DBL_MIN`, and `DBL_EPSILON` correspond to the return values of the `max`, `min`, and `epsilon` methods on `numeric_limits<double>` in C++.)

Here is the analogous C# code:

```Console.WriteLine("double.MaxValue = {0}", double.MaxValue);
Console.WriteLine("double.MinValue = {0}", double.MinValue);
Console.WriteLine("double.Epsilon  = {0}", double.Epsilon);```

The output of the C# code is as follows:

```double.MaxValue = 1.79769313486232E+308
double.MinValue = -1.79769313486232E+308
double.Epsilon  = 4.94065645841247E-324```

In short, C and C# have the same idea of “max”, but they have different ideas of “min” and “epsilon”.

The constants `DBL_MIN` and `double.MinValue` are different because they are minimizing over different ranges. `DBL_MIN` is the smallest positive value of a normalized `double`, and `double.MinValue` in C# is the smallest (i.e., most negative) finite value of a `double`.

The C constant `DBL_EPSILON` is the smallest positive double precision number `x` such that `1 + x` does not equal 1. Typically, a double has about 15 figures of precision, and so `DBL_EPSILON` is of the order of 10-16. (For a more precise description, see Anatomy of a floating point number.)

C# has no counterpart to `DBL_EPSILON`. The constant `double.Epsilon` in C# is something like the C constant `DBL_MIN`. `double.Epsilon` is the smallest possible positive value of a `double`, including denormalized values. `DBL_MIN` is the smallest positive value of a `double` restricted to normalized values.

Missing functionality

The list of mathematical functions in C# is minimal. Some of the missing functionality can be filled in easily. For example, `System.Math` does not include the inverse hyperbolic functions `asinh`, `acosh`, or `atanh`. But these can be computed via the following identities:

• asinh(x) = log(x + sqrt(x2 + 1))
• acosh(x) = log(x + sqrt(x2 - 1))
• atanh(x) = (log(1+x) - log(1-x))/2

However, other mathematical functions that you might expect will not be as easy to supply. For example, C# has no error function `erf(x)`. This function is not trivial to implement, though this link provides stand-alone C# code for erf.

Conclusions

In summary:

• Math functions are members of the `System.Math` class.
• Function names are capitalizations of traditional names, with a few exceptions.
• The numeric limit constants for `double`s look deceptively like C counterparts, but are not the same.
• C# does not come with support for advanced math functions.

History

• June 7, 2010: Initial version.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

About the Author

Singular Value Consulting
United States
I am an independent consultant in software development and applied mathematics. I help companies learn from their data to make better decisions.

Check out my blog or send me a note.

Follow on

Comments and Discussions

 First Prev Next
 Hi.   Nice port. I just thought it would be useful to add to the library the Phi (normal cumulative) function and its inverse. They use function erf of the library.   I hope it's useful. It's been written without if's because I have a GPGPU port in mind (GPUs don't like "if" branching).   Regards;   Douglas   ```  #region Phi (normal cumulative) and Inverse Phi   //Adapted from: http://home.online.no/~pjacklam/notes/invnorm/#The_distribution_function #region Constants private static double[] a = new double[] { -3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02, 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00 };   private static double[] b = new double[] { -5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02, 6.680131188771972e+01, -1.328068155288572e+01 };   private static double[] c = new double[] { -7.784894002430293e-03, -3.223964580411365e-01,-2.400758277161838e+00,-2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00 };   private static double[] d = new double[] { 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00 };   private static double ierfp_low = 0.02425; private static double ierfp_high = 0.97575; #endregion //Normal cumulative function public static double Phi(double x) { return 0.5 + 0.5 * erf(x * 0.707106781186547); }   //Inverse Normal cumulative function public static double invPhi(double p) { if (p > 1 || p < 0) throw new Exception("Error function inverse undefined for p > 1 or p < 0");   double q, r, x;   q = (p < ierfp_low) ? Math.Sqrt(-2 * Math.Log(p)) : (p < ierfp_high) ? p - 0.5 : Math.Sqrt(-2 * Math.Log(1 - p));   r = q * q;   x = (p < ierfp_low) ? (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1) : (p < ierfp_high) ? (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q / (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1) : -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);   double e = Phi(x) - p; double u = e * 2.506628274631 * Math.Exp(0.5 * x * x); x = x - u / (1 + x * u * 0.5);   return x; }   #endregion   ```
 OLS regression djonger 26-Nov-11 23:01
 C# Maths Packages Nonpareil 15-Jun-10 7:16
 double.Epsilon Günther M. FOIDL 15-Jun-10 4:02
 good article Rozis 9-Jun-10 14:01
 Last Visit: 31-Dec-99 19:00     Last Update: 30-Mar-15 22:47 Refresh 1

General    News    Suggestion    Question    Bug    Answer    Joke    Rant    Admin

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150327.1 | Last Updated 26 Jun 2014
Article Copyright 2010 by John D. Cook
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid